Tricky question on shader
Nicolas Rougier <[email protected]>
| Newsgroups | gmane.comp.python.opengl.user |
|---|---|
| Message-ID | <[email protected]> |
Hi folks, I've been playing with gaussian texture filtering using shaders and I obtained a strange "grid" effect on a completely uniform texture. Since all fragments get the same processing and same neighbouring values,I wonder if the grid is the result of some kind of artifact with floating points or the way texture coordinates are interpolated. Or I missed something completely obvious… I attached the code below. It is self-contained and you should see the grid I'm talking about. Nicolas ------------------------------------------------------------------------------ Special Offer -- Download ArcSight Logger for FREE! Finally, a world-class log management solution at an even better price-free! And you'll get a free "Love Thy Logs" t-shirt when you download Logger. Secure your free ArcSight Logger TODAY! http://p.sf.net/sfu/arcsisghtdev2dev _______________________________________________ PyOpenGL Homepage http://pyopengl.sourceforge.net _______________________________________________ PyOpenGL-Users mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/pyopengl-users
filter-gaussian.py
(text/x-python-script, 6.6 KB)
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import math
import ctypes
import numpy as np
import OpenGL.GL as gl
import OpenGL.GLUT as glut
class Shader:
def __init__(self, vert = None, frag = None, name=''):
self.uniforms = {}
self.name = name
self.handle = gl.glCreateProgram()
self.linked = False
self._build_shader(vert, gl.GL_VERTEX_SHADER)
self._build_shader(frag, gl.GL_FRAGMENT_SHADER)
self._link()
def _build_shader(self, strings, stype):
count = len(strings)
if count < 1:
return
shader = gl.glCreateShader(stype)
gl.glShaderSource(shader, strings)
gl.glCompileShader(shader)
status = gl.glGetShaderiv(shader, gl.GL_COMPILE_STATUS)
if not status:
print gl.glGetShaderInfoLog(shader)
else:
gl.glAttachShader(self.handle, shader)
def _link(self):
gl.glLinkProgram(self.handle)
temp = ctypes.c_int(0)
gl.glGetProgramiv(self.handle, gl.GL_LINK_STATUS, ctypes.byref(temp))
if not temp:
gl.glGetProgramiv(self.handle, gl.GL_INFO_LOG_LENGTH, ctypes.byref(temp))
log = gl.glGetProgramInfoLog(self.handle)
print log
else:
self.linked = True
def bind(self):
gl.glUseProgram(self.handle)
def unbind(self):
gl.glUseProgram(0)
def uniformf(self, name, *vals):
loc = self.uniforms.get(name, gl.glGetUniformLocation(self.handle,name))
self.uniforms[name] = loc
if len(vals) in range(1, 5):
{ 1 : gl.glUniform1f,
2 : gl.glUniform2f,
3 : gl.glUniform3f,
4 : gl.glUniform4f
}[len(vals)](loc, *vals)
def uniformi(self, name, *vals):
loc = self.uniforms.get(name, gl.glGetUniformLocation(self.handle,name))
self.uniforms[name] = loc
if len(vals) in range(1, 5):
{ 1 : gl.glUniform1i,
2 : gl.glUniform2i,
3 : gl.glUniform3i,
4 : gl.glUniform4i
}[len(vals)](loc, *vals)
vert = '''
void main()
{
gl_FrontColor = gl_Color;
gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;
gl_Position = gl_ModelViewProjectionMatrix*gl_Vertex;
}
'''
frag = '''
float
gaussian(float x)
{
float PI = 3.14159265358979323846264;
return exp(-2.0 * x * x) * sqrt(2.0 / PI);
}
vec4
filter( float x, vec4 c0, vec4 c1, vec4 c2, vec4 c3 )
{
vec4 r = c0 * gaussian(x+1.0); // h.x;
r += c1 * gaussian(x+0.0); // h.y;
r += c2 * gaussian(1.0-x); // h.z;
r += c3 * gaussian(2.0-x); // h.w;
return r;
}
vec4
interpolate( sampler2D texture, vec2 uv, vec2 pixel )
{
vec2 texel = uv/pixel - vec2(0.5,0.5) ;
vec2 f = fract(texel);
texel = (texel-fract(texel)+vec2(0.001,0.001))*pixel;
vec4 t0 = filter( f.x,
texture2D( texture, texel + vec2(-1, -1)*pixel ),
texture2D( texture, texel + vec2( 0, -1)*pixel ),
texture2D( texture, texel + vec2( 1, -1)*pixel ),
texture2D( texture, texel + vec2( 2, -1)*pixel ) );
vec4 t1 = filter( f.x,
texture2D( texture, texel + vec2(-1, 0)*pixel ),
texture2D( texture, texel + vec2( 0, 0)*pixel ),
texture2D( texture, texel + vec2( 1, 0)*pixel ),
texture2D( texture, texel + vec2( 2, 0)*pixel ) );
vec4 t2 = filter( f.x,
texture2D( texture, texel + vec2(-1, 1)*pixel ),
texture2D( texture, texel + vec2( 0, 1)*pixel ),
texture2D( texture, texel + vec2( 1, 1)*pixel ),
texture2D( texture, texel + vec2( 2, 1)*pixel ) );
vec4 t3 = filter( f.x,
texture2D( texture, texel + vec2(-1, 2)*pixel ),
texture2D( texture, texel + vec2( 0, 2)*pixel ),
texture2D( texture, texel + vec2( 1, 2)*pixel ),
texture2D( texture, texel + vec2( 2, 2)*pixel ) );
return filter( f.y, t0, t1, t2, t3 );
}
uniform vec2 pixel;
uniform sampler2D texture;
void main()
{
gl_FragColor = interpolate(texture, gl_TexCoord[0].xy, pixel);
}
'''
if __name__ == '__main__':
import sys
def on_display( ):
gl.glClearColor(1,1,1,1)
gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT)
x,y,w,h = gl.glGetIntegerv(gl.GL_VIEWPORT)
gl.glEnable( gl.GL_BLEND )
gl.glBlendFunc (gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA)
gl.glColor( 1, 0, 0, 1 )
shader.bind()
gl.glEnable( gl.GL_TEXTURE_2D )
gl.glActiveTexture( gl.GL_TEXTURE0 )
gl.glBindTexture( gl.GL_TEXTURE_2D, texture_id)
shader.uniformi('texture', 0)
shader.uniformf('pixel', 1.0/Z.shape[0], 1.0/Z.shape[1])
gl.glBegin( gl.GL_QUADS )
gl.glTexCoord2f( 0, 1 ), gl.glVertex2f( x, y )
gl.glTexCoord2f( 0, 0 ), gl.glVertex2f( x, y+h )
gl.glTexCoord2f( 1, 0 ), gl.glVertex2f( x+w, y+h )
gl.glTexCoord2f( 1, 1 ), gl.glVertex2f( x+w, y )
gl.glEnd()
shader.unbind()
glut.glutSwapBuffers( )
def on_reshape( width, height ):
gl.glViewport( 0, 0, width, height )
gl.glMatrixMode( gl.GL_PROJECTION )
gl.glLoadIdentity( )
gl.glOrtho( 0, width, 0, height, -1, 1 )
gl.glMatrixMode( gl.GL_MODELVIEW )
gl.glLoadIdentity( )
def on_keyboard( key, x, y ):
if key == '\033':
sys.exit( )
glut.glutInit( sys.argv )
glut.glutInitDisplayMode( glut.GLUT_DOUBLE | glut.GLUT_RGBA | glut.GLUT_DEPTH )
glut.glutCreateWindow( "glumpy filters" )
glut.glutReshapeWindow( 800, 800 )
glut.glutDisplayFunc( on_display )
glut.glutReshapeFunc( on_reshape )
glut.glutKeyboardFunc( on_keyboard )
def func3(x,y):
return (1-x/2+x**5+y**3)*np.exp(-x**2-y**2)
x = np.linspace(-3.0, 3.0, 32)
y = np.linspace(-3.0, 3.0, 32)
Z = func3(*np.meshgrid(x, y))
Z = (Z-Z.min())/(Z.max()-Z.min())
Z[:] = 0.5
texture_id = gl.glGenTextures(1)
gl.glPixelStorei( gl.GL_UNPACK_ALIGNMENT, 1 )
gl.glPixelStorei( gl.GL_PACK_ALIGNMENT, 1 )
gl.glBindTexture( gl.GL_TEXTURE_2D, texture_id )
gl.glTexParameterf( gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_NEAREST )
gl.glTexParameterf( gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST )
gl.glTexParameterf( gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_S, gl.GL_CLAMP )
gl.glTexParameterf( gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_T, gl.GL_CLAMP )
gl.glTexImage2D( gl.GL_TEXTURE_2D, 0, gl.GL_ALPHA,
Z.shape[0], Z.shape[1], 0, gl.GL_ALPHA, gl.GL_FLOAT, Z )
gl.glTexEnvf( gl.GL_TEXTURE_ENV, gl.GL_TEXTURE_ENV_MODE, gl.GL_MODULATE )
shader = Shader(vert,frag)
glut.glutMainLoop( )