BPL*_*BPL 5 python opengl shader glsl fragment-shader
Let's consider this mcve:
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *
import textwrap
from string import Template
def compile(shader_type, source):
identifier = glCreateShader(shader_type)
glShaderSource(identifier, source)
glCompileShader(identifier)
if not glGetShaderiv(identifier, GL_COMPILE_STATUS):
for i, l in enumerate(source.splitlines()):
print(f"{i+1}: {l}")
raise Exception(glGetShaderInfoLog(identifier).decode("utf-8"))
return identifier
def create_program(vs, fs):
vs_identifier = compile(GL_VERTEX_SHADER, vs)
fs_identifier = compile(GL_FRAGMENT_SHADER, fs)
program = glCreateProgram()
glAttachShader(program, vs_identifier)
glAttachShader(program, fs_identifier)
glLinkProgram(program)
if not glGetProgramiv(program, GL_LINK_STATUS):
raise RuntimeError(glGetProgramInfoLog(program))
return program
def set_uniform1f(prog, name, v0):
# print("set_uniform1f", name, glGetUniformLocation(prog, name))
glUniform1f(glGetUniformLocation(prog, name), v0)
def set_uniform1i(prog, name, v0):
# print("set_uniform1i", name, glGetUniformLocation(prog, name))
glUniform1i(glGetUniformLocation(prog, name), v0)
def set_uniform2f(prog, name, v0, v1):
# print("set_uniform2f", name, glGetUniformLocation(prog, name))
glUniform2f(glGetUniformLocation(prog, name), v0, v1)
class Window:
def __init__(self, w, h):
glutInit()
# glutInitContextVersion(3,2) # at least 3.2 is required, you can use a higer version when needed
# glutInitContextProfile(GLUT_CORE_PROFILE)
# glutInitContextFlags(GLUT_FORWARD_COMPATIBLE)
glutSetOption(GLUT_MULTISAMPLE, 16)
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH | GLUT_MULTISAMPLE)
glutInitWindowSize(w, h)
glutCreateWindow('Mcve uniforms')
glutReshapeFunc(self.reshape)
glutKeyboardFunc(self.keyboard_func)
glutKeyboardUpFunc(self.keyboard_up_func)
glutDisplayFunc(self.display)
glutIdleFunc(self.idle_func)
self.keys = {chr(i): False for i in range(256)}
# -------- Conflicting shader exposing bug --------
self.MAGIC_CONSTANT = 635
vs_code = textwrap.dedent("""\
void main()
{
gl_Position = ftransform();
}
""")
text = """\
#pragma optimize (off)
uniform vec2 resolution;
$block_declaration
vec3 f(vec2 x) {
x = sin(abs(x * 0.5));
float cs = cos(float($var_name) * 10037.5);
float ss = sin(float($var_name) * 12.5) * 0.09;
float t = sin(float($var_name)) * 0.5 + 0.5;
float d = sin(10. * length(x - vec2(cs, ss)) + mix(8., 10., t));
vec3 color = mix(vec3(0.8,0.86,0.85), vec3(0.52,0.72,0.79), sin(t) * 0.5);
return color*pow(d, 2.) / 5.;
}
void main() {
vec2 uv = (gl_FragCoord.xy / resolution.xy) * 2.0 - 1.0;
uv.x *= (resolution.x / resolution.y);
vec3 col = f(uv);
gl_FragColor = vec4(col*5.0, 1.0);
}
"""
VAR_NAME = "my_time"
fs_code0 = textwrap.dedent(Template(text).substitute(
block_declaration=f"int {VAR_NAME} = {self.MAGIC_CONSTANT};",
var_name=VAR_NAME
))
fs_code1 = textwrap.dedent(Template(text).substitute(
block_declaration=f"uniform int {VAR_NAME};",
var_name=VAR_NAME
))
print("SHADER0".center(80, '-'))
print(fs_code0)
print("SHADER1".center(80, '-'))
print(fs_code1)
# -------- Shader using time uniform --------
self.program0 = create_program(vs_code, fs_code0)
self.program1 = create_program(vs_code, fs_code1)
# -------- Setup --------
s = 1.0
glClearColor(1, 1, 1, 1)
glEnable(GL_DEPTH_TEST)
glMatrixMode(GL_PROJECTION)
glOrtho(-s, s, -s, s, -s, s)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
def keyboard_func(self, *args):
self.keys[args[0].decode("utf8")] = True
def keyboard_up_func(self, *args):
self.keys[args[0].decode("utf8")] = False
def display(self):
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
if self.keys['w']:
# Case a) Using uniform
glUseProgram(self.program0)
set_uniform2f(self.program0, "resolution", self.width, self.height)
else:
# Case b) Using constant with same value than uniform
glUseProgram(self.program1)
set_uniform1i(self.program1, "my_time", self.MAGIC_CONSTANT)
set_uniform2f(self.program1, "resolution", self.width, self.height)
s = 0.5
glBegin(GL_QUADS)
glVertex3f(-s, -s, 0)
glVertex3f(s, -s, 0)
glVertex3f(s, s, 0)
glVertex3f(-s, s, 0)
glEnd()
glutSwapBuffers()
def run(self):
glutMainLoop()
def idle_func(self):
glutPostRedisplay()
def reshape(self, w, h):
glViewport(0, 0, w, h)
self.width = w
self.height = h
if __name__ == '__main__':
Window(800, 600).run()
Run Code Online (Sandbox Code Playgroud)
After running you'll see these 2 fragment shaders are generated (you can switch between them by pressing 'w' key):
------------------------------------SHADER0-------------------------------------
#pragma optimize (off)
uniform vec2 resolution;
int my_time = 635;
vec3 f(vec2 x) {
x = sin(abs(x * 0.5));
float cs = cos(float(my_time) * 10037.5);
float ss = sin(float(my_time) * 12.5) * 0.09;
float t = sin(float(my_time)) * 0.5 + 0.5;
float d = sin(10. * length(x - vec2(cs, ss)) + mix(8., 10., t));
vec3 color = mix(vec3(0.8,0.86,0.85), vec3(0.52,0.72,0.79), sin(t) * 0.5);
return color*pow(d, 2.) / 5.;
}
void main() {
vec2 uv = (gl_FragCoord.xy / resolution.xy) * 2.0 - 1.0;
uv.x *= (resolution.x / resolution.y);
vec3 col = f(uv);
gl_FragColor = vec4(col*5.0, 1.0);
}
------------------------------------SHADER1-------------------------------------
#pragma optimize (off)
uniform vec2 resolution;
uniform int my_time;
vec3 f(vec2 x) {
x = sin(abs(x * 0.5));
float cs = cos(float(my_time) * 10037.5);
float ss = sin(float(my_time) * 12.5) * 0.09;
float t = sin(float(my_time)) * 0.5 + 0.5;
float d = sin(10. * length(x - vec2(cs, ss)) + mix(8., 10., t));
vec3 color = mix(vec3(0.8,0.86,0.85), vec3(0.52,0.72,0.79), sin(t) * 0.5);
return color*pow(d, 2.) / 5.;
}
void main() {
vec2 uv = (gl_FragCoord.xy / resolution.xy) * 2.0 - 1.0;
uv.x *= (resolution.x / resolution.y);
vec3 col = f(uv);
gl_FragColor = vec4(col*5.0, 1.0);
}
Run Code Online (Sandbox Code Playgroud)
One would expect both shaders to give exactly the same output. Unfortunately that's not the case, if you run this code you'll see how both look really different:
QUESTION:
Main reason being I'd like to have my uniform variables as hardcoded values in the shader without getting any different results after tweaking my shaders.
Specs where you can reproduce the bug
Specs where the bug won't show up