Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Issue with shaders/matrices - can't see object

I'm attempting to put a cube on the screen and light it. I'd like a phong shading on the cube.

When I run my code, I can see a background image but no cube.

I'm fairly sure the cube itself is correct as I've managed to display it with a solid-colour shader.

I've managed to get the shader program to compile but I can't see the cube at all. I don't know if GLES/LibGdx have a mechanism for run-time exceptions but I can't see anything in the logs.

I'm assuming that

  • The model is out of the field of view
  • The model is being rendered transparent
  • Both

I've tried to pare down my code to where I believe the problem lies. If you need to see anything else, just ask.

Setup

shader = new ShaderProgram(
        Gdx.files.internal("shaders/phongVertexShader.glsl"),
        Gdx.files.internal("shaders/phongFragmentShader.glsl"));
if (!shader.isCompiled()) {
    throw new IllegalStateException(shader.getLog());
}
mesh = Shapes.genCube();
mesh.getVertexAttribute(Usage.Position).alias = "a_position";
mesh.getVertexAttribute(Usage.Normal).alias = "a_normal";

Render

public void onRender() {
    Gdx.gl.glClearColor(0, 0, 0, 1);
    Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
    batch.setProjectionMatrix(camera.combined);

    angle += Gdx.graphics.getDeltaTime() * 40.0f;
    float aspect = Gdx.graphics.getWidth()
            / (float) Gdx.graphics.getHeight();
    projection.setToProjection(1.0f, 20.0f, 60.0f, aspect);
    view.idt().trn(0, 0, -2.0f);
    model.setToRotation(axis, angle);
    combined.set(projection).mul(view).mul(model);

    Gdx.gl20.glViewport(0, 0, Gdx.graphics.getWidth(),
        Gdx.graphics.getHeight());

    shader.begin();

    float[] light = {10, 10, 10};

    shader.setUniformMatrix("mvpMatrix", combined);
    shader.setUniformMatrix("mvMatrix", new Matrix4().translate(0, 0, -10));
    shader.setUniform3fv("vLightPosition", light, 0, 3);

    mesh.render(shader, GL20.GL_TRIANGLES);
    shader.end();
}

Vertex Shader

#version 330
in vec4 vVertex;
in vec3 vNormal;
uniform mat4 mvpMatrix;  // mvp = ModelViewProjection
uniform mat4 mvMatrix; // mv = ModelView
uniform mat3 normalMatrix;
uniform vec3 vLightPosition;
smooth out vec3 vVaryingNormal;
smooth out vec3 vVaryingLightDir;

void main(void) {
    vVaryingNormal = normalMatrix * vNormal;
    vec4 vPosition4 = mvMatrix * vVertex;
    vec3 vPosition3 = vPosition4.xyz / vPosition4.w;
    vVaryingLightDir = normalize(vLightPosition - vPosition3);
    gl_Position = mvpMatrix * vVertex;
}

Fragment Shader

#version 330
out vec4 vFragColor;
uniform vec4 ambientColor;
uniform vec4 diffuseColor;
uniform vec4 specularColor;
smooth in vec3 vVaryingNormal;
smooth in vec3 vVaryingLightDir;

void main(void) {
    float diff = max(0.0, dot(normalize(vVaryingNormal), normalize(vVaryingLightDir)));
    vFragColor = diff * diffuseColor;
    vFragColor += ambientColor;
    vec3 vReflection = normalize(reflect(-normalize(vVaryingLightDir),normalize(vVaryingNormal)));
    float spec = max(0.0, dot(normalize(vVaryingNormal), vReflection));

    if(diff != 0) {
        float fSpec = pow(spec, 32.0);
        vFragColor.rgb += vec3(fSpec, fSpec, fSpec);
    }
}

Can someone point me in the right direction?

like image 651
Basic Avatar asked Mar 13 '13 23:03

Basic


People also ask

Can Vertex Shader read texture?

The vertex shader 3.0 model supports texture lookup in the vertex shader using the texldl - vs texture load statement.

How do shaders work in opengl?

A Shader is a user-defined program designed to run on some stage of a graphics processor. Shaders provide the code for certain programmable stages of the rendering pipeline. They can also be used in a slightly more limited form for general, on-GPU computation.

What is a uniform variable in a shader?

A uniform is a global Shader variable declared with the "uniform" storage qualifier. These act as parameters that the user of a shader program can pass to that program. Their values are stored in a program object.

What is shader in image processing?

In computer graphics, a shader is a computer program that calculates the appropriate levels of light, darkness, and color during the rendering of a 3D scene - a process known as shading.


1 Answers

To answer this question it is going to take a decent amount of explanation and code. I will first start with the code:

LibGDX Code:

public class Test extends Game {
    private final FPSLogger fpsLogger = new FPSLogger();
    private ShaderProgram shader;
    private Mesh mesh;
    Matrix4 projection = new Matrix4();
    Matrix4 view = new Matrix4();
    Matrix4 model = new Matrix4();
    Matrix4 combined = new Matrix4();
    Matrix4 modelView = new Matrix4();
    Matrix3 normalMatrix = new Matrix3();
    Vector3 axis = new Vector3(1, 0, 1).nor();
    float angle = 45;

    private static final float[] light = { 20, 20, 20 };

    private static final float[] amb = { 0.2f, 0.2f, 0.2f, 1.0f };
    private static final float[] dif = { 0.5f, 0.5f, 0.5f, 1.0f };
    private static final float[] spec = { 0.7f, 0.7f, 0.7f, 1.0f };

    public Test() {}

    @Override public void create() {
        this.mesh = Shapes.genCube();
        ShaderProgram.pedantic = false;
        final String location = "shaders/phong";
        this.shader = new ShaderProgram(Gdx.files.internal(location + ".vsh").readString(), Gdx.files.internal(location + ".fsh").readString());
        if (!this.shader.isCompiled()) {
            Gdx.app.log("Problem loading shader:", this.shader.getLog());
        }

        Gdx.gl20.glEnable(GL20.GL_DEPTH_TEST);
    }

    @Override public void render() {
        super.render();
        this.fpsLogger.log();

        this.angle += Gdx.graphics.getDeltaTime() * 40.0f;
        final float aspect = Gdx.graphics.getWidth() / (float) Gdx.graphics.getHeight();
        this.projection.setToProjection(1.0f, 20.0f, 60.0f, aspect);
        this.view.idt().trn(0, 0, -2.0f);
        this.model.setToRotation(this.axis, this.angle);
        this.combined.set(this.projection).mul(this.view).mul(this.model);
        this.modelView.set(this.view).mul(this.model);

        Gdx.gl20.glViewport(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
        Gdx.gl20.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
        this.shader.begin();

        this.shader.setUniformMatrix("mvpMatrix", this.combined);
        this.shader.setUniformMatrix("mvMatrix", this.modelView);
        this.shader.setUniformMatrix("normalMatrix", this.normalMatrix.set(this.modelView).inv().transpose());
        this.shader.setUniform4fv("ambientColor", amb, 0, 4);
        this.shader.setUniform4fv("diffuseColor", dif, 0, 4);
        this.shader.setUniform4fv("specularColor", spec, 0, 4);
        this.shader.setUniform3fv("vLightPosition", light, 0, 3);

        this.mesh.render(this.shader, GL20.GL_TRIANGLES);

        this.shader.end();
    }

    @Override public void dispose() {
        if (this.mesh != null) {
            this.mesh.dispose();
        }
        if (this.shader != null) {
            this.shader.dispose();
        }
    }
}

Vertex Shader (phong.vsh)

attribute vec3 a_position;
attribute vec3 a_normal;
uniform mat4 mvpMatrix;  // mvp = ModelViewProjection
uniform mat4 mvMatrix; // mv = ModelView
uniform mat3 normalMatrix;
uniform vec3 vLightPosition;

varying vec3 vVaryingNormal;
varying vec3 vVaryingLightDir;

void main(void) {
    vVaryingNormal = normalMatrix * a_normal;
    vec4 vPosValue = vec4(a_position.x, a_position.y, a_position.z, 1.0);
    vec4 vPosition4 = mvMatrix * vPosValue;
    vec3 vPosition3 = a_position;
    vVaryingLightDir = normalize(vLightPosition - vPosition3);
    gl_Position = mvpMatrix * vPosValue;
}

Fragment Shader (phong.fsh)

#ifdef GL_ES
precision mediump float;
#endif

uniform vec4 ambientColor;
uniform vec4 diffuseColor;
uniform vec4 specularColor;
varying vec3 vVaryingNormal;
varying vec3 vVaryingLightDir;

void main(void) {
    float diff = max(0.0, dot(normalize(vVaryingNormal), normalize(vVaryingLightDir)));
    vec4 color = diff * diffuseColor;
    color += ambientColor;
    vec3 vReflection = normalize(reflect(-normalize(vVaryingLightDir),normalize(vVaryingNormal)));
    float spec = max(0.0, dot(normalize(vVaryingNormal), vReflection));

    if(diff != 0) {
        float fSpec = pow(spec, 128.0);
        color.rgb += vec3(fSpec, fSpec, fSpec);
    }

    gl_FragColor = color;
}

Explanation:

It doesn't look like a very good Phong shader because the normals for the cube are not properly calculated. Which you can find inside of the Shapes.genCube() but I will leave that for you to fix since I've provided everything else.

Make sure to look over the shader code, this is OpenGL ES 2.0 GLSL, which is different than the OpenGL 3.3 GLSL you have posted. These are some of the few differences between the versions.

What you need to do is make sure the values you provide the shader match the shader's variables. You also need to make sure to setup your matrices correctly and supply proper values for the light so that it displays correctly.

like image 119
Jyro117 Avatar answered Sep 28 '22 02:09

Jyro117