OpenGL Tricky question on shader

This topic is 2972 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

Recommended Posts

[font="Helvetica"]Hi folks,[/font] [font="Helvetica"]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…[/font] [font="Helvetica"]I attached the (python) code below and the vertex/fragment is at the top of the file.[/font]

[font="Helvetica"]Nicolas[/font]

[font="Helvetica"][source lang="python"][/font][font="Helvetica"] [/font]

#!/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

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);
}
'''

def __init__(self, vert = None, frag = None, name=''):
self.uniforms = {}
self.name = name
self.handle = gl.glCreateProgram()

def _build_shader(self, strings, stype):
count = len(strings)
if count < 1:
return
if not status:
else:

temp = ctypes.c_int(0)
if not temp:
gl.glGetProgramiv(self.handle, gl.GL_INFO_LOG_LENGTH, ctypes.byref(temp))
log = gl.glGetProgramInfoLog(self.handle)
print log
else:

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)

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 )

gl.glEnable( gl.GL_TEXTURE_2D )
gl.glActiveTexture( gl.GL_TEXTURE0 )
gl.glBindTexture( gl.GL_TEXTURE_2D, texture_id)
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()
glut.glutSwapBuffers( )

def on_reshape( width, height ):
gl.glViewport( 0, 0, width, height )
gl.glMatrixMode( gl.GL_PROJECTION )
gl.glOrtho( 0, width, 0, height, -1, 1 )
gl.glMatrixMode( gl.GL_MODELVIEW )

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 )
glut.glutMainLoop( )
[font="Helvetica"][/source][/font]

Share on other sites
Since you didn't specify a precision, glTexImage2D( gl.GL_TEXTURE_2D, 0, gl.GL_ALPHA,
the driver probably decided on GL_ALPHA8 which is a 8 bit integer (0..255)

http://www.opengl.org/wiki/Common_Mistakes#Image_precision

Share on other sites
try GL_CLAMP_TO_EDGE instead of GL_CLAMP on the texture.

Share on other sites
Thanks for the hint but it does not work. After further investigation, it seems that my Gaussian function is the responsible for the grid effect as illustrated below:

import matplotlib.pyplot as plt def gaussian(x): return np.exp(-2.0 * x * x) * np.sqrt(2.0 / np.pi); x = np.linspace(0,1,100) y = gaussian(x+1) + gaussian(x) + gaussian(1-x) + gaussian(2-x) plt.plot(x,y) plt.show() 

I got the function definition from the anti grain geometry library and I would have thought I was doing the same computation in the shader but obviously I missed a point.

Nicolas

Share on other sites
You might try this blur code

• Game Developer Survey

We are looking for qualified game developers to participate in a 10-minute online survey. Qualified participants will be offered a \$15 incentive for your time and insights. Click here to start!

• 15
• 11
• 9
• 11
• 15