Help with Shaders

Started by SilencePhil, September 15, 2015, 20:38:41

Previous topic - Next topic

SilencePhil

Hello,
i need help with some shader problems in my simple tile based 2d game.

Here are some images from the problem:

Normal (the black area is wanted and okay):
http://prntscr.com/8gr295

With vertex and fragment shader:
http://prntscr.com/8gr2sa

Vertex Shader:
#version 400 core

in vec3 position;

out vec3 color;

void main(void) {

    gl_Position = vec4(position, 1.0);
    color = vec3(0.5, 1.0, 0.5);
}


Fragment Shader:
#version 400 core

in vec3 color;

out vec4 outColor;

void main(void) {

    outColor = vec4(color, 1.0);
}


I don't know what is happening there, pls help :/

I hope that someone can help me with this.

SP

quew8

I don't see how this could be an issue with the shaders. At the same time, there is no way those shaders could produce the same output, if nothing else they don't use textures.

I'd suggest it's an issue elsewhere.

SilencePhil

Hey,

what else can cause this problem?

When i don't use shader everything is fine, but when i turn on shaders, it's looks like the second image.

I have implemented nice text rendering and a big feature that is missing is a nice shader for lightning etc.

I hope you can find a cause for this, if you need other information, tell me what and i can give it to you.

SP

quew8

I'm not really sure how you could just "turn off" shaders and it still work. Could you show an example of how you render something and let me know which OpenGL version you are using (and whether it is core, forward-compat etc.)

Kai

Using just any kind of shader does not make your whole game look better out of thin air... :)
You have to actually reimplement everything you are currently doing with the fixed-function pipeline (i.e. without shaders) using those shaders.
You have to do texture sampling manually, you have to implement your lighting model manually and you have to implement vertex transformations manually.
Once you "turn on shaders" then OpenGL stops doing all these things for you.
Currently, your shader just says: "Well, give me some vertices and I output them as normalized device coordinates as they are and paint everything in light green."

SilencePhil

Hey,
with turning off the shader i mean to comment out the line where the binding and uniform stuff happens :D

My goal is to have nice ambient and point light which can have different colors.

The opengl version is 3.3.0.

The rendering code for the world looks at the moment like this:

World:
    public void render() {

        glEnable(GL_TEXTURE_RECTANGLE_ARB);
        {
            glBindTexture(GL_TEXTURE_RECTANGLE_ARB, spriteSheet);
            {
                float targetX = Camera.getTarget().getX();
                float targetY = Camera.getTarget().getY();

                for (int x = 0; x < BLOCKS_WIDTH; x++) {
                    for (int y = 0; y < BLOCKS_HEIGHT; y++) {

                        int xPos = Math.round(targetX / World.BLOCK_SIZE);
                        int yPos = Math.round(targetY / World.BLOCK_SIZE);

                        if(xPos - x < RENDER_DISTANCE_X && yPos - y < RENDER_DISTANCE_Y && xPos - x > -RENDER_DISTANCE_X && yPos - y > -RENDER_DISTANCE_Y)
                            blocks[x][y].render();
                    }
                }
            }
            glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
        }
        glDisable(GL_TEXTURE_RECTANGLE_ARB);

        player.render();
    }


Block:
    public void render() {

        int x = type.getX();
        int y = type.getY();
        int x2 = type.getX() + type.getWidth();
        int y2 = type.getY() + type.getHeight();

        glBegin(GL_QUADS);
        {
            glTexCoord2f(x, y);
            glVertex2f(this.x, this.y);
            glTexCoord2f(x, y2);
            glVertex2f(this.x, this.y + type.getHeight());
            glTexCoord2f(x2, y2);
            glVertex2f(this.x + type.getWidth(), this.y + type.getHeight());
            glTexCoord2f(x2, y);
            glVertex2f(this.x + type.getWidth(), this.y);
        }
        glEnd();
    }


The opengl projection init stuff:
        /* OpenGL matrix setup */
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glOrtho(0, GatherWindow.WINDOW_WIDTH, GatherWindow.WINDOW_HEIGHT, 0, 1, -1);
        glMatrixMode(GL_MODELVIEW);

        /* Enable 2d textures */
        glEnable(GL_TEXTURE_2D);

        /* Enable blending e.g. for text rendering */
        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);


I am very happy with this, especially with my very very simple render distance thing, but i will code a chunk like system with VBO etc today.

The shader "only" needs to have lightning, so i don't need a shader for the world rendering yet. So i have some lights, binding the lighning shader to it and unbinding it after the light stuff.

How can i archieve that as simple as possible?

abcdef

As soon as you enable the programmable pipeline the fixed function pipeline is automatically disabled

example

glUseProgram(program);


Once you disable the programmable pipeline

glUseProgram(0);


You can then use the fixed function pipeline again from this point onwards. As you can see you cannot combine functionality from one type of pipeline to another. If you want to draw your vertices with the fixed function pipeline, you then need to use the fixed function pipeline for all the drawing actions which includes changing the color due to light.


quew8

You have to take it in steps. First write a shader that can render untransformed vertices in a solid colour where you specify (that's what yours does at the moment, but you should really be using generic attributes). Then make the colour modifiable too. Then add in matrix transforms. Then textured primitives. Then mess around for a bit to get a feel for it. Then you are ready to add lighting.

I'd advise going through the Lighthouse3D tutorials. They're the best GLSL tutorials I've come across: http://www.lighthouse3d.com/tutorials/glsl-tutorial/

SilencePhil

I have found that GLSL stuff from ligthhouse already, but sometimes it is not so clean/understandable how to work further with it for my requirements that i have.

I can't make a shader only for lightning? I don't need a shader for the world rendering, so i want to have some kind of stuff where i can bind the shader, do lightning with it and then unbind it and all that after world rendering?

quew8

You can have a shader just for the lighting but it also has to do all the other bits of rendering.

SilencePhil

So you mean like a vertex shader with gl_Position stuff etc.?

What is with the shaders from one of my replys above? They are correct, or?

quew8

The role of a vertex shader is to take vertex attributes like position, colour, normal and tex coords and work out the actual position and to pass on any information the fragment shader needs to the fragment shader.

The role of the fragment shader is to take all of the information passed on from the vertex shader and work out what colour the fragment should be.

Lighting falls into the fragment shader (mainly) jobs. But you can't do a fragment shader without a vertex shader and so you need to implement the whole pipeline in shaders.

SilencePhil

I have tested a few things, but the result i get is this:

http://prntscr.com/8hpv6o

Rendering:
        //glEnable(GL_BLEND);
        //glBlendFunc(GL_ONE, GL_ONE);

        shader.bind();
        shader.setUniform("lightLocation", new Vector2f(-50, -50));
        shader.setUniform("lightColor", new Vector3f(1f, 1f, 1f));
        shader.setUniform("ambientLight", new Vector3f(0.2f, 0.2f, 0.2f));
        shader.setUniform("baseColor", new Vector3f(0.5f, 0.0f, 0.0f));

        glBegin(GL_QUADS);
        {
            //glTexCoord2f(0, 0);
            glVertex2f(-50, -50);
            //glTexCoord2f(0, 1);
            glVertex2f(-50, -50 + 100);
            //glTexCoord2f(1, 0);
            glVertex2f(-50 + 100, -50 + 100);
            //glTexCoord2f(1, 1);
            glVertex2f(-50 + 100, -100);
        }
        glEnd();

        shader.unbind();

        //glDisable(GL_BLEND);


Vertex:
#version 120

void main() { 
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}


Fragment:
#version 120

uniform vec2 lightLocation;
uniform vec3 lightColor;
uniform vec3 ambientLight;
uniform vec3 baseColor;

void main() { 
    vec4 light = vec4(ambientLight, 1);
    vec4 color = vec4(baseColor,1);

    float distance = length(lightLocation - gl_FragCoord.xy);
    float attenuation = 1 / distance;
    vec4 lColor = vec4(attenuation, attenuation, attenuation, pow(attenuation, 3)) * vec4(lightColor, 1);
    color += lColor;

    gl_FragColor = color * light;
}


What's wrong with that?

quew8

There could be a lot of things wrong with it. Make it simpler until it works.

SilencePhil

Do you think that it is a good idea to setup one VBO like a renderer?
And then in the block drawing code something like renderer.begin(); and renderer.end(); which updates the vertices etc.?