From 8cec7e04eb71783caf03a8ac0e272d78491ec14b Mon Sep 17 00:00:00 2001 From: Elias Naur Date: Thu, 29 Jul 2021 08:15:50 +0200 Subject: [PATCH] gpu,gpu/shaders: [compute] decode sRGB texels in shader when EXT_sRGB is missing This change avoids the hard dependency on GPU support for sRGB encoded textures in the compute renderer. With this change and the previously added CPU fallback, Gio no longer rely on any GPU functionality outside the OpenGL ES 2.0 level. Fixes gio#49 Fixes gio#154 Fixes gio#97 Fixes gio#36 Fixes gio#172 Signed-off-by: Elias Naur --- gpu/compute.go | 52 ++++++++++++++++++++++------ gpu/gpu.go | 6 +--- gpu/shaders.go | 71 ++++++++++++++++++++++++++++++--------- gpu/shaders/material.frag | 10 +++++- 4 files changed, 107 insertions(+), 32 deletions(-) diff --git a/gpu/compute.go b/gpu/compute.go index 335d9fa7..50110545 100644 --- a/gpu/compute.go +++ b/gpu/compute.go @@ -42,6 +42,7 @@ type compute struct { texOps []textureOp viewport image.Point maxTextureDim int + srgb bool programs struct { elements computeProgram @@ -98,8 +99,14 @@ type compute struct { buffer sizedBuffer - uniforms *materialUniforms - uniBuf driver.Buffer + vert struct { + uniforms *materialVertUniforms + buf driver.Buffer + } + + frag struct { + buf driver.Buffer + } // CPU fields cpuTex cpu.ImageDescriptor @@ -154,11 +161,16 @@ type copyUniforms struct { _ [8]byte // Pad to 16 bytes. } -type materialUniforms struct { +type materialVertUniforms struct { scale [2]float32 pos [2]float32 } +type materialFragUniforms struct { + emulateSRGB float32 + _ [12]byte // Pad to 16 bytes +} + type collector struct { hasher maphash.Hash profile bool @@ -372,6 +384,7 @@ func newCompute(ctx driver.Device) (*compute, error) { g := &compute{ ctx: ctx, maxTextureDim: maxDim, + srgb: caps.Features.Has(driver.FeatureSRGB), conf: new(config), memHeader: new(memoryHeader), } @@ -447,15 +460,27 @@ func newCompute(ctx driver.Device) (*compute, error) { return nil, err } g.materials.layout = progLayout - g.materials.uniforms = new(materialUniforms) + g.materials.vert.uniforms = new(materialVertUniforms) - buf, err = ctx.NewBuffer(driver.BufferBindingUniforms, int(unsafe.Sizeof(*g.materials.uniforms))) + buf, err = ctx.NewBuffer(driver.BufferBindingUniforms, int(unsafe.Sizeof(*g.materials.vert.uniforms))) if err != nil { g.Release() return nil, err } - g.materials.uniBuf = buf + g.materials.vert.buf = buf g.materials.prog.SetVertexUniforms(buf) + var emulateSRGB materialFragUniforms + if !g.srgb { + emulateSRGB.emulateSRGB = 1.0 + } + buf, err = ctx.NewBuffer(driver.BufferBindingUniforms, int(unsafe.Sizeof(emulateSRGB))) + if err != nil { + g.Release() + return nil, err + } + buf.Upload(byteslice.Struct(&emulateSRGB)) + g.materials.frag.buf = buf + g.materials.prog.SetFragmentUniforms(buf) for _, shader := range shaders { if !g.useCPU { @@ -875,9 +900,9 @@ restart: } } // Transform to clip space: [-1, -1] - [1, 1]. - g.materials.uniforms.scale = [2]float32{2 / float32(texSize), 2 / float32(texSize)} - g.materials.uniforms.pos = [2]float32{-1, -1} - g.materials.uniBuf.Upload(byteslice.Struct(g.materials.uniforms)) + g.materials.vert.uniforms.scale = [2]float32{2 / float32(texSize), 2 / float32(texSize)} + g.materials.vert.uniforms.pos = [2]float32{-1, -1} + g.materials.vert.buf.Upload(byteslice.Struct(g.materials.vert.uniforms)) vertexData := byteslice.Slice(m.quads) n := pow2Ceil(len(vertexData)) m.buffer.ensureCapacity(false, g.ctx, driver.BufferBindingVertices, n) @@ -952,7 +977,11 @@ restart: a.tex = nil } sz := a.packer.maxDim - handle, err := g.ctx.NewTexture(driver.TextureFormatSRGBA, sz, sz, driver.FilterLinear, driver.FilterLinear, driver.BufferBindingTexture) + format := driver.TextureFormatSRGBA + if !g.srgb { + format = driver.TextureFormatRGBA8 + } + handle, err := g.ctx.NewTexture(format, sz, sz, driver.FilterLinear, driver.FilterLinear, driver.BufferBindingTexture) if err != nil { return fmt.Errorf("compute: failed to create image atlas: %v", err) } @@ -1316,7 +1345,8 @@ func (g *compute) Release() { g.materials.fbo, g.materials.tex, &g.materials.buffer, - g.materials.uniBuf, + g.materials.vert.buf, + g.materials.frag.buf, g.timers.t, } g.materials.cpuTex.Free() diff --git a/gpu/gpu.go b/gpu/gpu.go index a23f914e..deb6f1b9 100644 --- a/gpu/gpu.go +++ b/gpu/gpu.go @@ -9,7 +9,6 @@ package gpu import ( "encoding/binary" - "errors" "fmt" "image" "image/color" @@ -361,11 +360,8 @@ func New(api API) (GPU, error) { defer d.EndFrame() forceCompute := os.Getenv("GIORENDERER") == "forcecompute" feats := d.Caps().Features - if !feats.Has(driver.FeatureSRGB) { - return nil, errors.New("gpu: no sRGB texture formats found") - } switch { - case !forceCompute && feats.Has(driver.FeatureFloatRenderTargets): + case !forceCompute && feats.Has(driver.FeatureFloatRenderTargets) && feats.Has(driver.FeatureSRGB): return newGPU(d) } return newCompute(d) diff --git a/gpu/shaders.go b/gpu/shaders.go index 1edb6dfb..7f7394b7 100644 --- a/gpu/shaders.go +++ b/gpu/shaders.go @@ -5073,13 +5073,25 @@ void main() Hash: "e72e482d7f40b2949426017cb5aeb4d391fcfc0e9d42e73bffb5a1e5576e906d", } shader_material_frag = driver.ShaderSources{ - Name: "material.frag", - Inputs: []driver.InputLocation{{Name: "vUV", Location: 0, Semantic: "TEXCOORD", SemanticIndex: 0, Type: 0x0, Size: 2}}, + Name: "material.frag", + Inputs: []driver.InputLocation{{Name: "vUV", Location: 0, Semantic: "TEXCOORD", SemanticIndex: 0, Type: 0x0, Size: 2}}, + Uniforms: driver.UniformsReflection{ + Blocks: []driver.UniformBlock{{Name: "Color", Binding: 0}}, + Locations: []driver.UniformLocation{{Name: "_color.emulateSRGB", Type: 0x0, Size: 1, Offset: 0}}, + Size: 4, + }, Textures: []driver.TextureBinding{{Name: "tex", Binding: 0}}, GLSL100ES: `#version 100 precision mediump float; precision highp int; +struct Color +{ + float emulateSRGB; +}; + +uniform Color _58; + uniform mediump sampler2D tex; varying vec2 vUV; @@ -5095,9 +5107,12 @@ vec3 RGBtosRGB(vec3 rgb) void main() { vec4 texel = texture2D(tex, vUV); - vec3 param = texel.xyz; - vec3 _59 = RGBtosRGB(param); - texel = vec4(_59.x, _59.y, _59.z, texel.w); + if (_58.emulateSRGB == 0.0) + { + vec3 param = texel.xyz; + vec3 _71 = RGBtosRGB(param); + texel = vec4(_71.x, _71.y, _71.z, texel.w); + } gl_FragData[0] = texel; } @@ -5106,6 +5121,11 @@ void main() precision mediump float; precision highp int; +layout(std140) uniform Color +{ + float emulateSRGB; +} _58; + uniform mediump sampler2D tex; in vec2 vUV; @@ -5122,15 +5142,25 @@ vec3 RGBtosRGB(vec3 rgb) void main() { vec4 texel = texture(tex, vUV); - vec3 param = texel.xyz; - vec3 _59 = RGBtosRGB(param); - texel = vec4(_59.x, _59.y, _59.z, texel.w); + if (_58.emulateSRGB == 0.0) + { + vec3 param = texel.xyz; + vec3 _71 = RGBtosRGB(param); + texel = vec4(_71.x, _71.y, _71.z, texel.w); + } fragColor = texel; } `, GLSL130: `#version 130 +struct Color +{ + float emulateSRGB; +}; + +uniform Color _58; + uniform sampler2D tex; in vec2 vUV; @@ -5147,15 +5177,23 @@ vec3 RGBtosRGB(vec3 rgb) void main() { vec4 texel = texture(tex, vUV); - vec3 param = texel.xyz; - vec3 _59 = RGBtosRGB(param); - texel = vec4(_59.x, _59.y, _59.z, texel.w); + if (_58.emulateSRGB == 0.0) + { + vec3 param = texel.xyz; + vec3 _71 = RGBtosRGB(param); + texel = vec4(_71.x, _71.y, _71.z, texel.w); + } fragColor = texel; } `, GLSL150: `#version 150 +layout(std140) uniform Color +{ + float emulateSRGB; +} _58; + uniform sampler2D tex; in vec2 vUV; @@ -5172,14 +5210,17 @@ vec3 RGBtosRGB(vec3 rgb) void main() { vec4 texel = texture(tex, vUV); - vec3 param = texel.xyz; - vec3 _59 = RGBtosRGB(param); - texel = vec4(_59.x, _59.y, _59.z, texel.w); + if (_58.emulateSRGB == 0.0) + { + vec3 param = texel.xyz; + vec3 _71 = RGBtosRGB(param); + texel = vec4(_71.x, _71.y, _71.z, texel.w); + } fragColor = texel; } `, - HLSL: "DXBC\x9e\x87LD\xf3\x17\n\x06\\\xb7\x98\x94\xa9PKe\x01\x00\x00\x00\xc8\x04\x00\x00\x06\x00\x00\x008\x00\x00\x00\xbc\x01\x00\x00D\x03\x00\x00\xc0\x03\x00\x00`\x04\x00\x00\x94\x04\x00\x00Aon9|\x01\x00\x00|\x01\x00\x00\x00\x02\xff\xffT\x01\x00\x00(\x00\x00\x00\x00\x00(\x00\x00\x00(\x00\x00\x00(\x00\x01\x00$\x00\x00\x00(\x00\x00\x00\x00\x00\x00\x02\xff\xffQ\x00\x00\x05\x00\x00\x0f\xa0=\n\x87?\xaeGa\xbd\x00\x00\x00\x00\x00\x00\x00\x00Q\x00\x00\x05\x01\x00\x0f\xa0\x1c.M\xbbR\xb8NAvT\xd5>\x00\x00\x00\x00\x1f\x00\x00\x02\x00\x00\x00\x80\x00\x00\x03\xb0\x1f\x00\x00\x02\x00\x00\x00\x90\x00\b\x0f\xa0B\x00\x00\x03\x00\x00\x0f\x80\x00\x00\xe4\xb0\x00\b\xe4\xa0\x0f\x00\x00\x02\x01\x00\x01\x80\x00\x00\x00\x80\x0f\x00\x00\x02\x01\x00\x02\x80\x00\x00U\x80\x0f\x00\x00\x02\x01\x00\x04\x80\x00\x00\xaa\x80\x05\x00\x00\x03\x01\x00\a\x80\x01\x00\xe4\x80\x01\x00\xaa\xa0\x0e\x00\x00\x02\x02\x00\x01\x80\x01\x00\x00\x80\x0e\x00\x00\x02\x02\x00\x02\x80\x01\x00U\x80\x0e\x00\x00\x02\x02\x00\x04\x80\x01\x00\xaa\x80\x04\x00\x00\x04\x01\x00\a\x80\x02\x00\xe4\x80\x00\x00\x00\xa0\x00\x00U\xa0\x02\x00\x00\x03\x01\x00\b\x80\x00\x00\x00\x80\x01\x00\x00\xa0\x05\x00\x00\x03\x02\x00\a\x80\x00\x00\xe4\x80\x01\x00U\xa0X\x00\x00\x04\x00\x00\x01\x80\x01\x00\xff\x80\x01\x00\x00\x80\x02\x00\x00\x80\x02\x00\x00\x03\x01\x00\x01\x80\x00\x00U\x80\x01\x00\x00\xa0X\x00\x00\x04\x00\x00\x02\x80\x01\x00\x00\x80\x01\x00U\x80\x02\x00U\x80\x02\x00\x00\x03\x01\x00\x01\x80\x00\x00\xaa\x80\x01\x00\x00\xa0X\x00\x00\x04\x00\x00\x04\x80\x01\x00\x00\x80\x01\x00\xaa\x80\x02\x00\xaa\x80\x01\x00\x00\x02\x00\b\x0f\x80\x00\x00\xe4\x80\xff\xff\x00\x00SHDR\x80\x01\x00\x00@\x00\x00\x00`\x00\x00\x00Z\x00\x00\x03\x00`\x10\x00\x00\x00\x00\x00X\x18\x00\x04\x00p\x10\x00\x00\x00\x00\x00UU\x00\x00b\x10\x00\x032\x10\x10\x00\x00\x00\x00\x00e\x00\x00\x03\xf2 \x10\x00\x00\x00\x00\x00h\x00\x00\x02\x03\x00\x00\x00E\x00\x00\t\xf2\x00\x10\x00\x00\x00\x00\x00F\x10\x10\x00\x00\x00\x00\x00F~\x10\x00\x00\x00\x00\x00\x00`\x10\x00\x00\x00\x00\x00/\x00\x00\x05r\x00\x10\x00\x01\x00\x00\x00F\x02\x10\x00\x00\x00\x00\x008\x00\x00\nr\x00\x10\x00\x01\x00\x00\x00F\x02\x10\x00\x01\x00\x00\x00\x02@\x00\x00vT\xd5>vT\xd5>vT\xd5>\x00\x00\x00\x00\x19\x00\x00\x05r\x00\x10\x00\x01\x00\x00\x00F\x02\x10\x00\x01\x00\x00\x002\x00\x00\x0fr\x00\x10\x00\x01\x00\x00\x00F\x02\x10\x00\x01\x00\x00\x00\x02@\x00\x00=\n\x87?=\n\x87?=\n\x87?\x00\x00\x00\x00\x02@\x00\x00\xaeGa\xbd\xaeGa\xbd\xaeGa\xbd\x00\x00\x00\x00\x1d\x00\x00\nr\x00\x10\x00\x02\x00\x00\x00F\x02\x10\x00\x00\x00\x00\x00\x02@\x00\x00\x1c.M;\x1c.M;\x1c.M;\x00\x00\x00\x008\x00\x00\nr\x00\x10\x00\x00\x00\x00\x00F\x02\x10\x00\x00\x00\x00\x00\x02@\x00\x00R\xb8NAR\xb8NAR\xb8NA\x00\x00\x00\x006\x00\x00\x05\x82 \x10\x00\x00\x00\x00\x00:\x00\x10\x00\x00\x00\x00\x007\x00\x00\tr \x10\x00\x00\x00\x00\x00F\x02\x10\x00\x02\x00\x00\x00F\x02\x10\x00\x01\x00\x00\x00F\x02\x10\x00\x00\x00\x00\x00>\x00\x00\x01STATt\x00\x00\x00\n\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00RDEF\x98\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x1c\x00\x00\x00\x00\x04\xff\xff\x00\x01\x00\x00m\x00\x00\x00\\\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00i\x00\x00\x00\x02\x00\x00\x00\x05\x00\x00\x00\x04\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x00\x01\x00\x00\x00\r\x00\x00\x00_tex_sampler\x00tex\x00Microsoft (R) HLSL Shader Compiler 10.1\x00\xab\xab\xabISGN,\x00\x00\x00\x01\x00\x00\x00\b\x00\x00\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x03\x03\x00\x00TEXCOORD\x00\xab\xab\xabOSGN,\x00\x00\x00\x01\x00\x00\x00\b\x00\x00\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x0f\x00\x00\x00SV_Target\x00\xab\xab", + HLSL: "DXBC`l\xc5\r\xe5m\xb2n{\xec\x1c^\xe6\xcao\x04\x01\x00\x00\x00\xc0\x05\x00\x00\x06\x00\x00\x008\x00\x00\x00\xec\x01\x00\x00\xc8\x03\x00\x00D\x04\x00\x00X\x05\x00\x00\x8c\x05\x00\x00Aon9\xac\x01\x00\x00\xac\x01\x00\x00\x00\x02\xff\xffx\x01\x00\x004\x00\x00\x00\x01\x00(\x00\x00\x004\x00\x00\x004\x00\x01\x00$\x00\x00\x004\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x02\xff\xffQ\x00\x00\x05\x01\x00\x0f\xa0=\n\x87?\xaeGa\xbd\x00\x00\x00\x00\x00\x00\x00\x00Q\x00\x00\x05\x02\x00\x0f\xa0\x1c.M\xbbR\xb8NAvT\xd5>\x00\x00\x00\x00\x1f\x00\x00\x02\x00\x00\x00\x80\x00\x00\x03\xb0\x1f\x00\x00\x02\x00\x00\x00\x90\x00\b\x0f\xa0B\x00\x00\x03\x00\x00\x0f\x80\x00\x00\xe4\xb0\x00\b\xe4\xa0\x05\x00\x00\x03\x01\x00\b\x80\x00\x00\x00\xa0\x00\x00\x00\xa0\x0f\x00\x00\x02\x01\x00\x01\x80\x00\x00\x00\x80\x0f\x00\x00\x02\x01\x00\x02\x80\x00\x00U\x80\x0f\x00\x00\x02\x01\x00\x04\x80\x00\x00\xaa\x80\x05\x00\x00\x03\x01\x00\a\x80\x01\x00\xe4\x80\x02\x00\xaa\xa0\x0e\x00\x00\x02\x02\x00\x01\x80\x01\x00\x00\x80\x0e\x00\x00\x02\x02\x00\x02\x80\x01\x00U\x80\x0e\x00\x00\x02\x02\x00\x04\x80\x01\x00\xaa\x80\x04\x00\x00\x04\x01\x00\a\x80\x02\x00\xe4\x80\x01\x00\x00\xa0\x01\x00U\xa0\x02\x00\x00\x03\x02\x00\x01\x80\x00\x00\x00\x80\x02\x00\x00\xa0\x05\x00\x00\x03\x02\x00\x0e\x80\x00\x00\x1b\x80\x02\x00U\xa0X\x00\x00\x04\x03\x00\x01\x80\x02\x00\x00\x80\x01\x00\x00\x80\x02\x00\xff\x80\x02\x00\x00\x03\x03\x00\b\x80\x00\x00U\x80\x02\x00\x00\xa0X\x00\x00\x04\x03\x00\x02\x80\x03\x00\xff\x80\x01\x00U\x80\x02\x00\xaa\x80\x02\x00\x00\x03\x03\x00\b\x80\x00\x00\xaa\x80\x02\x00\x00\xa0X\x00\x00\x04\x03\x00\x04\x80\x03\x00\xff\x80\x01\x00\xaa\x80\x02\x00U\x80X\x00\x00\x04\x00\x00\a\x80\x01\x00\xff\x81\x03\x00\xe4\x80\x00\x00\xe4\x80\x01\x00\x00\x02\x00\b\x0f\x80\x00\x00\xe4\x80\xff\xff\x00\x00SHDR\xd4\x01\x00\x00@\x00\x00\x00u\x00\x00\x00Y\x00\x00\x04F\x8e \x00\x00\x00\x00\x00\x01\x00\x00\x00Z\x00\x00\x03\x00`\x10\x00\x00\x00\x00\x00X\x18\x00\x04\x00p\x10\x00\x00\x00\x00\x00UU\x00\x00b\x10\x00\x032\x10\x10\x00\x00\x00\x00\x00e\x00\x00\x03\xf2 \x10\x00\x00\x00\x00\x00h\x00\x00\x02\x04\x00\x00\x00E\x00\x00\t\xf2\x00\x10\x00\x00\x00\x00\x00F\x10\x10\x00\x00\x00\x00\x00F~\x10\x00\x00\x00\x00\x00\x00`\x10\x00\x00\x00\x00\x00/\x00\x00\x05r\x00\x10\x00\x01\x00\x00\x00F\x02\x10\x00\x00\x00\x00\x008\x00\x00\nr\x00\x10\x00\x01\x00\x00\x00F\x02\x10\x00\x01\x00\x00\x00\x02@\x00\x00vT\xd5>vT\xd5>vT\xd5>\x00\x00\x00\x00\x19\x00\x00\x05r\x00\x10\x00\x01\x00\x00\x00F\x02\x10\x00\x01\x00\x00\x002\x00\x00\x0fr\x00\x10\x00\x01\x00\x00\x00F\x02\x10\x00\x01\x00\x00\x00\x02@\x00\x00=\n\x87?=\n\x87?=\n\x87?\x00\x00\x00\x00\x02@\x00\x00\xaeGa\xbd\xaeGa\xbd\xaeGa\xbd\x00\x00\x00\x00\x1d\x00\x00\nr\x00\x10\x00\x02\x00\x00\x00F\x02\x10\x00\x00\x00\x00\x00\x02@\x00\x00\x1c.M;\x1c.M;\x1c.M;\x00\x00\x00\x008\x00\x00\nr\x00\x10\x00\x03\x00\x00\x00F\x02\x10\x00\x00\x00\x00\x00\x02@\x00\x00R\xb8NAR\xb8NAR\xb8NA\x00\x00\x00\x007\x00\x00\tr\x00\x10\x00\x01\x00\x00\x00F\x02\x10\x00\x02\x00\x00\x00F\x02\x10\x00\x01\x00\x00\x00F\x02\x10\x00\x03\x00\x00\x00\x18\x00\x00\b\x82\x00\x10\x00\x01\x00\x00\x00\x01@\x00\x00\x00\x00\x00\x00\n\x80 \x00\x00\x00\x00\x00\x00\x00\x00\x007\x00\x00\tr \x10\x00\x00\x00\x00\x00\xf6\x0f\x10\x00\x01\x00\x00\x00F\x02\x10\x00\x01\x00\x00\x00F\x02\x10\x00\x00\x00\x00\x006\x00\x00\x05\x82 \x10\x00\x00\x00\x00\x00:\x00\x10\x00\x00\x00\x00\x00>\x00\x00\x01STATt\x00\x00\x00\f\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00RDEF\f\x01\x00\x00\x01\x00\x00\x00\x94\x00\x00\x00\x03\x00\x00\x00\x1c\x00\x00\x00\x00\x04\xff\xff\x00\x01\x00\x00\xe4\x00\x00\x00|\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x89\x00\x00\x00\x02\x00\x00\x00\x05\x00\x00\x00\x04\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x00\x01\x00\x00\x00\r\x00\x00\x00\x8d\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00_tex_sampler\x00tex\x00Color\x00\xab\x8d\x00\x00\x00\x01\x00\x00\x00\xac\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc4\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x02\x00\x00\x00\xd4\x00\x00\x00\x00\x00\x00\x00_58_emulateSRGB\x00\x00\x00\x03\x00\x01\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00Microsoft (R) HLSL Shader Compiler 10.1\x00ISGN,\x00\x00\x00\x01\x00\x00\x00\b\x00\x00\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x03\x03\x00\x00TEXCOORD\x00\xab\xab\xabOSGN,\x00\x00\x00\x01\x00\x00\x00\b\x00\x00\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x0f\x00\x00\x00SV_Target\x00\xab\xab", } shader_material_vert = driver.ShaderSources{ Name: "material.vert", diff --git a/gpu/shaders/material.frag b/gpu/shaders/material.frag index e21b79f3..d0a1b715 100644 --- a/gpu/shaders/material.frag +++ b/gpu/shaders/material.frag @@ -10,6 +10,12 @@ layout(location = 0) in vec2 vUV; layout(location = 0) out vec4 fragColor; +layout(binding=0) uniform Color { + // If emulateSRGB is set (!= 0), the input texels are sRGB encoded. We save the + // conversion step below, at the cost of texture filtering in sRGB space. + float emulateSRGB; +}; + vec3 RGBtosRGB(vec3 rgb) { bvec3 cutoff = greaterThanEqual(rgb, vec3(0.0031308)); vec3 below = vec3(12.92)*rgb; @@ -19,6 +25,8 @@ vec3 RGBtosRGB(vec3 rgb) { void main() { vec4 texel = texture(tex, vUV); - texel.rgb = RGBtosRGB(texel.rgb); + if (emulateSRGB == 0.0) { + texel.rgb = RGBtosRGB(texel.rgb); + } fragColor = texel; }