I have an NVidia example that uses an ARB Assembly shader:
!!ARBfp1.0
TEX result.color, fragment.texcoord, texture[0], RECT;
END
Now I would like to translate that into a GLSL shader. This is what I've come up with:
uniform sampler2D tex;
void main(void)
{
vec4 col = texture2D ( tex, gl_TexCoord[0] );
gl_FragColor = vec4(col.r, col.g, col.b, col.a);
}
I was hoping to see no change in the resulting rendering, but sadly I only get a black texture.
I've already made sure that the tex sampler is set correctly. Also my GLSL code compiles with no errors. For debugging I tried to make my shader even simpler:
void main(void)
{
gl_FragColor = vec4(1,0,0,1);
}
This gives me a red texture. Thus my basic setup seems to be OK.
Pay attention to the 4th parameter of TEX. It says RECT, so the sampler needs to have sampler2DRect type.
uniform sampler2DRect tex;
void main(void) {
gl_FragColor = texture2DRect(tex, gl_TexCoord[0]);
}
Related
I'm trying to translate some old OpenGL code to modern OpenGL. This code is reading data from a texture and displaying it. The fragment shader is currently created using ARB_fragment_program commands:
static const char *gl_shader_code =
"!!ARBfp1.0\n"
"TEX result.color, fragment.texcoord, texture[0], RECT; \n"
"END";
GLuint program_id;
glGenProgramsARB(1, &program_id);
glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, program_id);
glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei) strlen(gl_shader_code ), (GLubyte *) gl_shader_code );
I'd simply like to translate this into GLSL code. I think the fragment shader should look something like this:
#version 430 core
uniform sampler2DRect s;
void main(void)
{
gl_FragColor = texture2DRect(s, ivec2(gl_FragCoord.xy), 0);
}
But I'm not sure of a couple of details:
Is this the right usage of texture2DRect?
Is this the right usage of gl_FragCoord?
The texture is being fed with a pixel buffer object using GL_PIXEL_UNPACK_BUFFER target.
I think you can just use the standard sampler2D instead of sampler2DRect (if you do not have a real need for it) since, quoting the wiki, "From a modern perspective, they (rectangle textures) seem essentially useless.".
You can then change your texture2DRect(...) to texture(...) or texelFetch(...) (to mimic your rectangle fetching).
Since you seem to be using OpenGL 4, you do not need to (should not ?) use gl_FragColor but instead declare an out variable and write to it.
Your fragment shader should look something like this in the end:
#version 430 core
uniform sampler2D s;
out vec4 out_color;
void main(void)
{
out_color = texelFecth(s, vec2i(gl_FragCoord.xy), 0);
}
#Zouch, thank you very much for your response. I took it and worked on this for a bit. My final cores were very similar to what you suggested. For the record the final vertex and fragment shaders I implemented were as follows:
Vertex Shader:
#version 330 core
layout(location = 0) in vec3 vertexPosition_modelspace;
layout(location = 1) in vec2 vertexUV;
out vec2 UV;
uniform mat4 MVP;
void main()
{
gl_Position = MVP * vec4(vertexPosition_modelspace, 1);
UV = vertexUV;
}
Fragment Shader:
#version 330 core
in vec2 UV;
out vec3 color;
uniform sampler2D myTextureSampler;
void main()
{
color = texture2D(myTextureSampler, UV).rgb;
}
That seemed to work.
I have a simple compositing system which is supposed to render different textures and a background texture into an FBO. It also renders some primitives.
Here's an example:
I'm rendering using a simple GLSL shader for the texture and another one for the primitive. Also, I'm waiting for each shader to finish using glFinish after each glDrawArrays call.
So basically:
tex shader (background tex)
tex shader (tex 1)
primitive shader
tex shader (tex 2)
tex shader (tex 3)
When I only do this once, it works. But if I do another render pass directly after the first one finished, some textures just aren't rendered.
The primitive however is always rendered.
This doesn't happen always, but the more textures I draw, the more often this occurs.
Thus, I'm assuming that this is a timing problem.
I tried to troubleshoot for the last two days and I just can't find the reason for this.
I'm 100% sure that the textures are always valid (I downloaded them using glGetTexImage to verify).
Here are my texture shaders.
Vertex shader:
#version 150
uniform mat4 mvp;
in vec2 inPosition;
in vec2 inTexCoord;
out vec2 texCoordV;
void main(void)
{
texCoordV = inTexCoord;
gl_Position = mvp * vec4(inPosition, 0.0, 1.0);
}
Fragment shader:
#version 150
uniform sampler2D tex;
in vec2 texCoordV;
out vec4 fragColor;
void main(void)
{
fragColor = texture(tex, texCoordV);
}
And here's my invocation:
NSRect drawDestRect = NSMakeRect(xPos, yPos, str.texSize.width, str.texSize.height);
NLA_VertexRect rect = NLA_VertexRectFromNSRect(drawDestRect);
int texID = 0;
NLA_VertexRect texCoords = NLA_VertexRectFromNSRect(NSMakeRect(0.0f, 0.0f, 1.0f, 1.0f));
NLA_VertexRectFlipY(&texCoords);
[self.texApplyShader.arguments[#"inTexCoord"] setValue:&texCoords forNumberOfVertices:4];
[self.texApplyShader.arguments[#"inPosition"] setValue:&rect forNumberOfVertices:4];
[self.texApplyShader.arguments[#"tex"] setValue:&texID forNumberOfVertices:1];
GetError();
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, str.texName);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
glFinish();
The setValue:forNumberOfCoordinates: function is an object-based wrapper around OpenGL's parameter application functions. It basically does this:
glBindVertexArray(_vertexArrayObject);
glBindBuffer(GL_ARRAY_BUFFER, _vertexBufferObject);
glBufferData(GL_ARRAY_BUFFER, bytesForGLType * numVertices, value, GL_DYNAMIC_DRAW);
glEnableVertexAttribArray((GLuint)self.boundLocation);
glVertexAttribPointer((GLuint)self.boundLocation, numVectorElementsForType, GL_FLOAT, GL_FALSE, 0, 0);
Here are two screenshots of what it should look like (taken after first render pass) and what it actually looks like (taken after second render pass):
https://www.dropbox.com/s/0nmquelzo83ekf6/GLRendering_issues_correct.png?dl=0
https://www.dropbox.com/s/7aztfba5mbeq5sj/GLRendering_issues_wrong.png?dl=0
(in this example, the background texture is just black)
The primitive shader is as simple as it gets:
Vertex:
#version 150
uniform mat4 mvp;
uniform vec4 inColor;
in vec2 inPosition;
out vec4 colorV;
void main (void)
{
colorV = inColor;
gl_Position = mvp * vec4(inPosition, 0.0, 1.0);
}
Fragment:
#version 150
in vec4 colorV;
out vec4 fragColor;
void main(void)
{
fragColor = colorV;
}
Found the issue... I didn't realize that the FBO is drawn to the screen already after the first render pass. This happens on a different thread and wasn't locked properly.
Apparently the context was switched while the compositing took place which explains why it caused different issues randomly depending on when the second thread switched the context.
I have the following piece of shader code that works perfectly with GLSL #130, but I would like to convert it to code that works with version #330 (as somehow the #130 version doesn't work on my Ubuntu machine with a Geforce 210; the shader does nothing). After several failed attempts (I keep getting undescribed link errors) I've decided to ask for some help. The code below dynamically changes the contrast and brightness of a texture using the uniform variables Brightness and Contrast. I have implemented it in Python using PyOpenGL:
def createShader():
"""
Compile a shader that adjusts contrast and brightness of active texture
Returns
OpenGL.shader - reference to shader
dict - reference to variables that can be passed to the shader
"""
fragmentShader = shaders.compileShader("""#version 130
uniform sampler2D Texture;
uniform float Brightness;
uniform float Contrast;
uniform vec4 AverageLuminance;
void main(void)
{
vec4 texColour = texture2D(Texture, gl_TexCoord[0].st);
gl_FragColor = mix(texColour * Brightness,
mix(AverageLuminance, texColour, Contrast), 0.5);
}
""", GL_FRAGMENT_SHADER)
shader = shaders.compileProgram(fragmentShader)
uniform_locations = {
'Brightness': glGetUniformLocation( shader, 'Brightness' ),
'Contrast': glGetUniformLocation( shader, 'Contrast' ),
'AverageLuminance': glGetUniformLocation( shader, 'AverageLuminance' ),
'Texture': glGetUniformLocation( shader, 'Texture' )
}
return shader, uniform_locations
I've looked up the changes that need to made for the new GLSL version and tried changing the fragment shader code to the following, but then only get non-descriptive Link errors:
fragmentShader = shaders.compileShader("""#version 330
uniform sampler2D Texture;
uniform float Brightness;
uniform float Contrast;
uniform vec4 AverageLuminance;
in vec2 TexCoord;
out vec4 FragColor;
void main(void)
{
vec4 texColour = texture2D(Texture, TexCoord);
FragColor = mix(texColour * Brightness,
mix(AverageLuminance, texColour, Contrast), 0.5);
}
""", GL_FRAGMENT_SHADER)
Is there anyone that can help me with this conversion?
I doubt that raising the shader version profile will solve any issue. #version 330 is OpenGL-3.3 and according to the NVidia product website the maximum OpenGL version supported by the GeForce 210 is OpenGL-3.1, i.e. #version 140
I created no vertex shader cause I didn't think I'd need one (I wouldn't know what I should make it do). It worked before without any vertex shader as well.
Probably only as long as you didn't use a fragment shader or before you were attempting to use a texture. The fragment shader needs input variables, coming from a vertex shader, to have something it can use as texture coordinates. TexCoord is not a built-in variable (and with higher GLSL versions any builtin variables suitable for the job have been removed), so you need to fill that with value (and sense) in a vertex shader.
the glGetString(GL_VERSION) on the NVidia machine reads out OpenGL version 3.3.0. This is Ubuntu, so it might be possible that it differs with the windows specifications?
Do you have the NVidia propriatary drivers installed? And are they actually used? Check with glxinfo or glGetString(GL_RENDERER). OpenGL-3.3 is not too far from OpenGL-3.1 and in theory OpenGL major versions map to hardware capabilities.
I have a very disturbing problem with glsl in WebGL.
This shader works as expected:
uniform sampler2D tColor;
uniform sampler2D tNormal;
varying vec2 vUv;
void main() {
gl_FragColor = texture2D( tColor, vUv );
}
But this one behaves total different:
uniform sampler2D tColor;
uniform sampler2D tNormal;
varying vec2 vUv;
void main() {
vec4 test = texture2D( tNormal, vUv );
gl_FragColor = texture2D( tColor, vUv );
}
By accessing the tNormal texture, the tColor texture is overridden. How is this possible?
I have seen similar behavior in the past, and it's almost always because I'm binding my textures improperly. The most recent incident was caused when I attempted to bind my textures like so:
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, colorTexture);
gl.uniform1i(colorUniform, gl.TEXTURE0);
gl.activeTexture(gl.TEXTURE1);
gl.bindTexture(gl.TEXTURE_2D, normalTexture);
gl.uniform1i(normalUniform, gl.TEXTURE1);
When the correct syntax is actually:
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, colorTexture);
gl.uniform1i(colorUniform, 0); // 0 to indicate texture unit 0!
gl.activeTexture(gl.TEXTURE1);
gl.bindTexture(gl.TEXTURE_2D, normalTexture);
gl.uniform1i(normalUniform, 1); // 1 to indicate texture unit 1!
This is a fairly common mistake, and unfortunately WebGL doesn't actually throw an error on the first code snippet (a subject of recent discussion in the WebGL mailing list) and it can appear to work in limited cases, so it's easy to mistakenly think that it's valid code.
I don't know if this is your specific problem, but it's probably the best advice I can provide without further details.
I'm working on implementing deferred shading to my game. I have rendered the diffuse textures to a render target, and I have lighting rendered to a render target. Both of which I know are fine because I can render them straight to the screen with no problems. What I want to do is combine both the diffuse map and the light map in a shader to create a final image. Here is my current fragment shader, which results in a black screen.
#version 110
uniform sampler2D diffuseMap;
uniform sampler2D lightingMap;
void main()
{
vec4 color = texture(diffuseMap, gl_TexCoord[0].st);
vec4 lighting = texture(lightingMap, gl_TexCoord[0].st);
vec4 finalColor = color;
gl_FragColor = finalColor;
}
Shouldn't this result in the same thing as just straight up drawing the diffuse map?
I set the sampler2d with this method
void ShaderProgram::setUniformTexture(const std::string& name, GLint t) {
GLint var = getUniformLocation(name);
glUniform1i(var, t);
}
GLint ShaderProgram::getUniformLocation(const std::string& name) {
if(mUniformValues.find(name) != mUniformValues.end()) {
return mUniformValues[name];
}
GLint var = glGetUniformLocation(mProgram, name.c_str());
mUniformValues[name] = var;
return var;
}
EDIT: Some more information. Here is the code where I use the shader. I set the two textures, and draw a blank square for the shader to use. I know for sure, my render targets are working, as I said before, because I can draw them fine using the same getTextureId as I do here.
graphics->useShader(mLightingCombinedShader);
mLightingCombinedShader->setUniformTexture("diffuseMap", mDiffuse->getTextureId());
mLightingCombinedShader->setUniformTexture("lightingMap", mLightMap->getTextureId());
graphics->drawPrimitive(mScreenRect, 0, 0);
graphics->clearShader();
void GraphicsDevice::useShader(ShaderProgram* p) {
glUseProgram(p->getId());
}
void GraphicsDevice::clearShader() {
glUseProgram(0);
}
And the vertex shader
#version 110
varying vec2 texCoord;
void main()
{
texCoord = gl_MultiTexCoord0.xy;
gl_Position = ftransform();
}
In GLSL version 110 you should use:
texture2D(diffuseMap, gl_TexCoord[0].st); // etc.
instead of just the texture function.
And then to combine the textures, just multiply the colours together, i.e.
gl_FragColor = color * lighting;
glUniform1i(var, t);
The glUniform functions affect the program that is currently in use. That is, the last program that glUseProgram was called on. If you want to set the uniform for a specific program, you have to use it first.
The problem ended up being that I didn't enable the texture coordinates for the screen rectangle I was drawing.