GLSL renders textures wrong - java

I am trying to make a lighting system, the program changes the texture(block) brightness depends on the light it gets, and the program does it for every block(texture) that is visible to the player.
However, the lighting system works perfectly, but when it comes to rendering with shaders everything gets destroyed.
This code is in the render loop -
float light = Lighting.checkLight(mapPosY, mapPosX, this); // Returns the light the current block gets
map[mapPos].light = light; // Applies the light to the block
Shaders.block.setUniformf("lightBlock", light); // Sets the light value to the shader's uniform, to change the brightness of the current block / texture.
batch.draw(map[mapPos].TEXTURE, (mapPosX * Block.WIDTH), (mapPosY * Block.HEIGHT), Block.WIDTH, Block.HEIGHT); // Renders the block / texture to the screen.
The result is pretty random..
As i said the first two lines work perfectly, the problem is probably is in the third line or in the shader itself.
The shader:
Vertex shader -
attribute vec4 a_color;
attribute vec3 a_position;
attribute vec2 a_texCoord0;
uniform mat4 u_projTrans;
varying vec4 vColor;
varying vec2 vTexCoord;
void main() {
vColor = a_color;
vTexCoord = a_texCoord0;
gl_Position = u_projTrans * vec4(a_position, 1.0f);
}
Fragment shader -
varying vec4 vColor;
varying vec2 vTexCoord;
uniform vec2 screenSize;
uniform sampler2D tex;
uniform float lightBlock;
const float outerRadius = .65, innerRadius = .4, intensity = .6;
const float SOFTNESS = 0.6;
void main() {
vec4 texColor = texture2D(tex, vTexCoord) * vColor;
vec2 relativePosition = gl_FragCoord.xy / screenSize - .5;
float len = length(relativePosition);
float vignette = smoothstep(outerRadius, innerRadius, len);
texColor.rgb = mix(texColor.rgb, texColor.rgb * vignette * lightBlock, intensity);
gl_FragColor = texColor;
}

I fixed the problem.. but i dont have any idea why it fixed it.
Thanks to Pedro, i focused more on the render loop instead of the shader itself.
Before the loop i added those 2 lines -
List<Integer> lBlocks = new ArrayList<Integer>();
Shaders.block.setUniformf("lightBlock", 0.3f);
Basically I created an array to store the bright blocks later on.
I set the uniform of the shader to be 0.3f which means pretty dark. the value should be 0-1f.
Now in the render loop, inside the for -
float light = Lighting.checkLight(mapPosY, mapPosX, this);
map[mapPos].light = light;
if( light == 1.0f) {
lBlocks.add(mapPos);
} else {
batch.draw(map[mapPos].TEXTURE, (mapPosX * Block.WIDTH), (mapPosY * Block.HEIGHT), Block.WIDTH, Block.HEIGHT);
}
As you can see, the bright blocks i add to the array and the dark ones i render, i set the uniform to 0.3f before the render loop as you can in the first code sample.
After the render loop i loop again through the bright blocks.. because we didn't render them.
Shaders.block.setUniformf("lightBlock", 1.0f);
for(int i = 0; i < lBlocks.size(); i++) {
batch.draw(map[lBlocks.get(i)].TEXTURE, ((lBlocks.get(i) % width) * Block.WIDTH), ((lBlocks.get(i) / width) * Block.HEIGHT), Block.WIDTH, Block.HEIGHT);
}
Now i rendered the bright blocks and it works.. the result was good.
But I don't have any idea why its like that, its like cutting the render loop to two, one for dark blocks and one for the bright ones.
Thanks :)

Related

Writing raw data to texture using GLSL, lwjgl

currently, I need the fragment shader to write to a texture(which it does), but rather than overwriting, it blends. Here is the fragment shader itself
#version 400 core
in vec2 pass_textureCoordinates;
out vec4 out_Color;
layout(location = 1) out vec4 out_location0;
uniform sampler2D modelTexture;
uniform sampler2D bumpTexture;
uniform sampler2D overlayTexture;
uniform sampler2D scratchLevels;
void main(void)
{
vec2 txt = pass_textureCoordinates;
vec4 base = texture(overlayTexture,txt);
vec4 over = texture(modelTexture,txt);
float baseA = base[3] * (1.0f - over[3]);
float overA = over[3];
float finalA = base[3] + (1.0f - base[3]) * overA;
if(finalA == 0)
{
out_Color[0] = 0;
out_Color[1] = 0;
out_Color[2] = 0;
}
else
{
out_Color[0] = (base[0] * baseA + over[0] * overA) / finalA;
out_Color[1] = (base[1] * baseA + over[1] * overA) / finalA;
out_Color[2] = (base[2] * baseA + over[2] * overA) / finalA;
}
out_Color[3] = finalA;
out_location0 = out_Color;
}
How can I write to the texture with out blending?
Edit: I need to overwrite the alpha channel as well
Blending depends on the blend function and can be disabled (glDisable(GL_BLEND)).
If you're using the traditional alpha blending function (glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)) or premultiplied alpha blending (glBlendFunc(GL_SRC_ALPHA, GL_ONE)), you can treat the texture as opaque by setting the output alpha channel to 1:
out_Color[3] = finalA;
out_Color[3] = 1.0;
Well you have several solutions to choose from:
the easiest is just to Disable Blending before the render call glDisable(GL_BLEND) and enable it again afterwards
You could just clear the data of the texture before rendering (if that is what you want) with opengl calls, e.g. glClear(GL_COLOR_BUFFER_BIT) and glClearColor(r,g,b)
change the alpha in your fragment shader e.g. to
if(out_Color.a > 0) out_Color = vec4(vec3(0,0,0)*(1.0-out_Color.a) + out_Color.rgb*out_Color.a, 1.0); this is just manually setting the background to black, but you could also discard it if out_Color.a == 0 (just discard;, that would - at least without a glClear call - cause the old data to stay visible at this pixel).
I hope I was able to help you :)

GLSL Smooth border shader

I'm looking for a specific shader or an idea for another approach to get the desired result.
A picture shows the desired result (left-side input, right-side output):
I already experimented with modifying a simple vignette shader:
varying vec4 v_color;
varying vec2 v_texCoord0;
uniform vec2 u_resolution;
uniform sampler2D u_sampler2D;
const float outerRadius = .65, innerRadius = .4, intensity = .6;
void main() {
vec4 color = texture2D(u_sampler2D, v_texCoord0) * v_color;
vec2 relativePosition = gl_FragCoord.xy / u_resolution - .5;
float len = length(relativePosition);
float vignette = smoothstep(outerRadius, innerRadius, len);
color.rgb = mix(color.rgb, color.rgb * vignette, intensity);
gl_FragColor = color;
}
I think it's more confusing than helpful when I show you my modified code. I tried to imitate the same concept as of the vignette shader: Used the bounding box of the island, transforming x,y,width,height in screenCoords and get the relative position of fragCoords to island's center (normal vignette would use the screen resolution instead the island 'resolution'). Then I wanted to invert the vignette effect (inside dark, outside fade out)
Unfortunately it doesn't work and I think whole approach should be changed.
Second idea is to place a dark light in all islands on my map. (with Box2DLights)
But this might be a little expensive?
Any other ideas?

OpenGL ES 2.0 Android Clipping Color

i'm using my fragment shader to clip objects in OpenGL ES 2.0. Everything is working well, however the colour of the clipped surface is all black... I can not figure out how to change the colour (well ideally I'd want to make a similar texture to the rest of the object. I have included the code for my fragment shader below.
precision mediump float;
varying vec2 texCoord;
varying vec3 v_Normal;
varying vec3 v_Position;
varying vec4 originalPosition;
uniform sampler2D texSampler2D;
uniform vec3 lightPosition;
uniform vec4 lightColor;
void main()
{
vec3 L = normalize(lightPosition - v_Position);
vec3 N = normalize(v_Normal);
float NdotL = max(dot(N,L),0.0);
if(originalPosition.y >= 2.0){
discard;
}else{
gl_FragColor = NdotL * lightColor * texture2D(texSampler2D, texCoord);
}
}
Using discard in a fragment shader doesn't render anything to the pixel, it just leaves it exactly as it was before, so the black color is probably your clear color or whatever you had rendered previously. If you want to render a particular color to the pixels you are currently discarding, add another uniform to your shader for the clip color, like this:
uniform vec4 clipColor;
Set it in the same way you set the lightColor, then instead of discarding the pixel when clipping, you can set the pixel to the clip color:
if(originalPosition.y >= 2.0) {
gl_FragColor = clipColor;
} else {
gl_FragColor = NdotL * lightColor * texture2D(texSampler2D, texCoord);
}

Using deferred rendering, getting blank output

So I'm working with Java/LibGDX and I'm trying to set up the very basics of deferred rendering, namely rendering the actual game art to one color buffer of an FBO and the corresponding normals to another color buffer of the FBO.
(So essentially, I'm wanting to create this and this by using multiple-render-targets.)
My problem is my end output is blank, as if nothing is being rendered or is being rendered incorrectly.
My shader (vertex and fragment)
I'm sort of sure this works, since if I just render some sprites completely normally with it enabled to the screen (not an FBO), they do render.
#version 150
in vec4 a_position;
in vec4 a_color;
in vec2 a_texCoord0;
uniform mat4 u_projTrans;
out vec4 v_color;
out vec2 v_texCoords;
void main()
{
v_color = a_color;
v_color.a = v_color.a * (255.0/254.0);
v_texCoords = a_texCoord0;
gl_Position = u_projTrans * a_position;
}
#version 150
#ifdef GL_ES
#define LOWP lowp
precision mediump float;
#else
#define LOWP
#endif
in LOWP vec4 v_color;
in vec2 v_texCoords;
uniform sampler2D u_texture;
uniform sampler2D u_normal;
out vec4 fragColor;
void main()
{
gl_FragData[0] = v_color * texture(u_texture, v_texCoords);
gl_FragData[1] = texture(u_normal, v_texCoords);
}
The following code is in the render loop.
The basic idea is I'm doing binding the two color buffers of the FBO with glDrawBuffers. I then bind two texture units, game art and normal'd game art. My shader above is supposed to take this and output game art to one color buffer and the corresponding normal art to the other.
// Position the camera.
_cameraRef.position.set(_stage.getWidth() * 0.5f, _stage.getHeight() * 0.5f, 0);
// Update the camera, SpriteBatch, and map renderer.
_cameraRef.update();
_spriteBatch.setProjectionMatrix(_cameraRef.combined);
_mapRenderer.setView(_cameraRef);
// Bind the color texture units of the FBO (multiple-render-targets).
Gdx.gl30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, _gBufferFBOHandle);
IntBuffer intBuffer = BufferUtils.newIntBuffer(2);
intBuffer.put(GL30.GL_COLOR_ATTACHMENT0);
intBuffer.put(GL30.GL_COLOR_ATTACHMENT1);
Gdx.gl30.glDrawBuffers(2, intBuffer);
// Draw!
Gdx.gl30.glClearColor(0, 0, 0, 1);
Gdx.gl30.glClear(GL30.GL_COLOR_BUFFER_BIT);
_spriteBatch.setShader(_shaderGBuffer);
_spriteBatch.begin();
_tilesAtlasNormal.bind(1); // Using multiple texture units to draw art and normals at same time to the two color buffers of the FBO.
_tilesAtlas.bind(0);
_mapRenderer.renderTileLayer(_mapLayerBackground);
_spriteBatch.end();
_spriteBatch.setShader(null);
// Bind the default FBO.
Gdx.gl30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, 0);
// Draw the contents of the FBO onto the screen to see what it looks like.
Gdx.gl30.glClearColor(0, 0, 0, 1);
Gdx.gl30.glClear(GL30.GL_COLOR_BUFFER_BIT);
_spriteBatch.begin();
_spriteBatch.draw(_gBufferTexture1, 0.0f, 0.0f); // <-- This texture is blank? It's the texture that was just rendered to above.
_spriteBatch.end();
So like I said, the end output is blank. I'm sure the FBO I create is valid since I check with glCheckFramebufferStatus.
It's just when I take the color texture(s) from that FBO and draw them to the screen, they're blank. I don't know where I'm going wrong.
Appreciate any input.
Last Ive checked the gl30 wasnt really ready for prime time in LibGDX.
That said, Ive achieved exactly what you want, but in gl20. Even if you have other reasons to use gl30, perhaps you will find my implementation useful source, video.
Don't forget to rewind your intbuffer:
IntBuffer intBuffer = BufferUtils.newIntBuffer(2);
intBuffer.put(GL30.GL_COLOR_ATTACHMENT0);
intBuffer.put(GL30.GL_COLOR_ATTACHMENT1);
intBuffer.rewind();

Vertex world position in glsl, JOGL

so i've been trying to implement bump mapping for some time and i have it working in some way. So it renders the texture and shadowing correct but does not change as the light source moves around I determined that it applies the light source moving around from the source (0,0) and not where the light source is in the world. How do i determine the world position of the fragment in the shader? I am a bit stuck at the moment, any help would be appreciated.
--vertex shader
void main()
{
gl_TexCoord[0] = gl_MultiTexCoord0;
// Set the position of the current vertex
gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;
}
--fragment shader
uniform sampler2D color_texture;
uniform sampler2D normal_texture;
uniform vec4 lightColor;
uniform vec3 falloff;
uniform vec3 lightPos;
uniform vec2 resolution;
uniform float ambience;
//uniform float lightDirection;
void main()
{
// Extract the normal from the normal map
vec3 normal = normalize(texture2D(normal_texture, gl_TexCoord[0].st).rgb * 2.0 - 1.0);
// Determine where the light is positioned
vec3 light_pos = normalize(lightPos);
//vec3 light_pos = normalize(vec3(1.0, 1.0, 0.5));
// Calculate the lighting diffuse value, the ambience is the darkness due to no light
float diffuse = max(dot(normal, light_pos), 0.0);
//direction
float lightDir = length(vec3(lightPos.xy - (gl_FragCoord.xy / resolution.xy), lightPos.z));
//calculate attenuation
float attenuation = 1.0 / ( falloff.x + (falloff.y*lightDir) + (falloff.z*lightDir*lightDir) );
//calculate the final color
vec3 color = diffuse * texture2D(color_texture, gl_TexCoord[0].st).rgb;
// Set the output color of our current pixel
gl_FragColor = vec4(color, 1.0);
}
--jogl, java code hooking up the shader
int shaderProgram = ShaderControl.enableShader(gl, shaderName);
//apply vars
int diffuseTextureVariableLocation = gl.getGL2().glGetUniformLocation(shaderProgram, "color_texture");
int normalColorVariableLocation = gl.getGL2().glGetUniformLocation(shaderProgram, "normal_texture");
int lightPositionVariableLocation = gl.getGL2().glGetUniformLocation(shaderProgram, "lightPos");
int lightColorVariableLocation = gl.getGL2().glGetUniformLocation(shaderProgram, "lightColor");
int falloffVariableLocation = gl.getGL2().glGetUniformLocation(shaderProgram, "falloff");
int resolutionVariableLocation = gl.getGL2().glGetUniformLocation(shaderProgram, "resolution");
int ambienceVariableLocation = gl.getGL2().glGetUniformLocation(shaderProgram, "ambience");
gl.getGL2().glUniform1i(diffuseTextureVariableLocation, 0);
gl.getGL2().glUniform1i(normalColorVariableLocation, 1);
gl.getGL2().glUniform3f(lightPositionVariableLocation, positionLight.x, positionLight.y, 1.5f);
gl.getGL2().glUniform4f(lightColorVariableLocation, 1f, 1.0f, 1.0f, 1f);
gl.getGL2().glUniform3f(falloffVariableLocation,.4f, 3f, 20f);
gl.getGL2().glUniform2f(resolutionVariableLocation, Game._viewPortDimension.width, Game._viewPortDimension.height);
gl.getGL2().glUniform1f(ambienceVariableLocation, 0.93f);
gl.getGL2().glActiveTexture(GL2.GL_TEXTURE1);
normalTexture.bind(gl);
//bind diffuse color to texture unit 0
gl.getGL2().glActiveTexture(GL2.GL_TEXTURE0);
texture.bind(gl);
//draw the texture and apply the bump mapping shader
drawTexture(gl, worldOffsetX, worldOffsetY, x, y, depth, rotation, percentageToDraw, width, height, texture);
ShaderControl.disableShader(gl);
Kind regards
Johandre
First, make sure you really need that. Once you are, you can create a varying vec3 in your fragment shaders that gets interpolated from the vertex shader that holds the world position. In order to do that, make sure you have separate modelview matrix and projection matrix. (I prefer having only a projection matrix for the games I made so far). Use the output of the modelview matrix for your varying vec3.

Categories