6

画面に立方体を置いて光らせようとしています。立方体にフォンシェーディングをお願いします。

コードを実行すると、背景画像は表示されますが、立方体は表示されません。

単色のシェーダーで表示できたので、立方体自体は正しいと確信しています。

シェーダー プログラムをコンパイルすることはできましたが、立方体がまったく表示されません。GLES/LibGdx に実行時例外のメカニズムがあるかどうかはわかりませんが、ログには何も表示されません。

私はそれを仮定しています

  • モデルが視野外にある
  • モデルは透明にレンダリングされています
  • 両方

問題があると思われる場所までコードを切り詰めようとしました。他に何か見る必要がある場合は、お尋ねください。

設定

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";

与える

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

頂点シェーダー

#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;
}

フラグメント シェーダー

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

誰かが私を正しい方向に向けることができますか?

4

1 に答える 1

4

この質問に答えるには、かなりの量の説明とコードが必要になります。最初にコードから始めます。

LibGDX コード:

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

頂点シェーダー (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;
}

フラグメント シェーダー (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;
}

説明:

立方体の法線が適切に計算されていないため、あまり良い Phong シェーダーには見えません。これは Shapes.genCube() 内で見つけることができますが、他のすべてを提供したので、修正するために残します。

シェーダー コードを確認してください。これは OpenGL ES 2.0 GLSL であり、投稿した OpenGL 3.3 GLSL とは異なります。これらは、バージョン間のいくつかの違いの一部です。

必要なことは、シェーダーに提供する値がシェーダーの変数と一致することを確認することです。また、正しく表示されるように、マトリックスを正しく設定し、ライトに適切な値を指定する必要があります。

于 2013-03-14T23:17:10.577 に答える