java - GLSL LWJGL 问题/着色器无能为力?

标签 java opengl glsl lwjgl

好的,所以我正在尝试让这里的教程发挥作用:http://lwjgl.org/wiki/index.php?title=GLSL_Shaders_with_LWJGL

我的问题是为什么我的着色器在此示例中没有执行任何操作?我对 GLSL 很陌生。

这是主类的代码

import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.util.glu.GLU;

/*
* Sets up the Display, the GL context, and runs the main game
loop.
*
* @author Stephen Jones
*/
public class GLSLTest{

    Box box;
    private boolean done=false; //game runs until done is set to true

    public GLSLTest(){
        init();

        while(!done){
            if(Display.isCloseRequested())
            done=true;
            render();
            Display.update();
        }

        Display.destroy();
    }

    private void render(){
        GL11.glClear(GL11.GL_COLOR_BUFFER_BIT |
        GL11.GL_DEPTH_BUFFER_BIT);
        GL11.glLoadIdentity();

        box.draw();
    }

    private void init(){
        int w=1024;
        int h=768;

        try{
            Display.setDisplayMode(new DisplayMode(w, h));
            Display.setVSyncEnabled(true);
            Display.setTitle("Shader Setup");
            Display.create();
        }catch(Exception e){
            System.out.println("Error setting up display");
            System.exit(0);
        }

        GL11.glViewport(0,0,w,h);
        GL11.glMatrixMode(GL11.GL_PROJECTION);
        GL11.glLoadIdentity();
        GLU.gluPerspective(45.0f, ((float)w/(float)h),0.1f,100.0f);
        GL11.glMatrixMode(GL11.GL_MODELVIEW);
        GL11.glLoadIdentity();
        GL11.glShadeModel(GL11.GL_SMOOTH);
        GL11.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
        GL11.glClearDepth(1.0f);
        GL11.glEnable(GL11.GL_DEPTH_TEST);
        GL11.glDepthFunc(GL11.GL_LEQUAL);
        GL11.glHint(GL11.GL_PERSPECTIVE_CORRECTION_HINT,
        GL11.GL_NICEST);

        box = new Box();
    }

    public static void main(String[] args){
        new GLSLTest();
    }
}

这是 Box 类的代码:

import org.lwjgl.opengl.GL11;
import java.io.BufferedReader;
import java.io.FileReader;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.ARBShaderObjects;
import org.lwjgl.opengl.ARBVertexShader;
import org.lwjgl.opengl.ARBFragmentShader;
import org.lwjgl.opengl.Util;

/**
* The vertex and fragment shaders are setup when the box object is
* constructed. They are applied to the GL state prior to the box
* being drawn, and released from that state after drawing.
* @author Stephen Jones
*/
public class Box {

    /*
    * if the shaders are setup ok we can use shaders, otherwise we just
    * use default settings
    */
    private boolean useShader=true;

    /*
    * program shader, to which is attached a vertex and fragment shaders.
    * They are set to 0 as a check because GL will assign unique int
    * values to each
    */
    private int shader=0;
    private int vertShader=0;
    private int fragShader=0;

    public Box(){

        /*
        * create the shader program. If OK, create vertex
        * and fragment shaders
        */
        shader=ARBShaderObjects.glCreateProgramObjectARB();

        if(shader!=0){
            vertShader=createVertShader("screen.vert");
            fragShader=createFragShader("screen.frag");
        }
        else useShader=false;

        /*
        * if the vertex and fragment shaders setup sucessfully,
        * attach them to the shader program, link the sahder program
        * (into the GL context I suppose), and validate
        */
        if(vertShader !=0 && fragShader !=0){
            ARBShaderObjects.glAttachObjectARB(shader, vertShader);
            ARBShaderObjects.glAttachObjectARB(shader, fragShader);
            ARBShaderObjects.glLinkProgramARB(shader);
            ARBShaderObjects.glValidateProgramARB(shader);
            useShader=printLogInfo(shader);
        }else useShader=false;
    }

    /*
    * If the shader was setup succesfully, we use the shader. Otherwise
    * we run normal drawing code.
    */
    public void draw(){
        if(useShader) {
            ARBShaderObjects.glUseProgramObjectARB(shader);
        }
        GL11.glLoadIdentity();
        GL11.glTranslatef(0.0f, 0.0f, -10.0f);
        GL11.glColor3f(1.0f, 1.0f, 1.0f);//white

        GL11.glBegin(GL11.GL_QUADS);
        GL11.glVertex3f(-1.0f, 1.0f, 0.0f);
        GL11.glVertex3f(1.0f, 1.0f, 0.0f);
        GL11.glVertex3f(1.0f, -1.0f, 0.0f);
        GL11.glVertex3f(-1.0f, -1.0f, 0.0f);
        GL11.glEnd();

        //release the shader
        ARBShaderObjects.glUseProgramObjectARB(0);

    }

    /*
    * With the exception of syntax, setting up vertex and fragment shaders
    * is the same.
    * @param the name and path to the vertex shader
    */
    private int createVertShader(String filename){
        //vertShader will be non zero if succefully created

        vertShader=ARBShaderObjects.glCreateShaderObjectARB(ARBVertexShader.GL_VERTEX_SHADER_ARB);
        //if created, convert the vertex shader code to a String
        if(vertShader==0){return 0;}
        String vertexCode="";
        String line;
        try{
            BufferedReader reader=new BufferedReader(new FileReader(filename));
            while((line=reader.readLine())!=null){
                vertexCode+=line + "\n";
            }
        }catch(Exception e){
            System.out.println("Fail reading vertex shading code");
            return 0;
        }
        /*
        * associate the vertex code String with the created vertex shader
        * and compile
        */
        ARBShaderObjects.glShaderSourceARB(vertShader, vertexCode);
        ARBShaderObjects.glCompileShaderARB(vertShader);
        //if there was a problem compiling, reset vertShader to zero
        if(!printLogInfo(vertShader)){
            vertShader=0;
        }
        //if zero we won't be using the shader
        return vertShader;
    }

    //same as per the vertex shader except for method syntax
    private int createFragShader(String filename){

        fragShader=ARBShaderObjects.glCreateShaderObjectARB(ARBFragmentShader.GL_FRAGMENT_SHADER_ARB);
        if(fragShader==0){return 0;}
            String fragCode="";
            String line;
        try{
            BufferedReader reader=new BufferedReader(new FileReader(filename));
            while((line=reader.readLine())!=null){
                fragCode+=line + "\n";
            }
        }catch(Exception e){
            System.out.println("Fail reading fragment shading code");
            return 0;
        }
        ARBShaderObjects.glShaderSourceARB(fragShader, fragCode);
        ARBShaderObjects.glCompileShaderARB(fragShader);
        if(!printLogInfo(fragShader)){
            fragShader=0;
        }

        return fragShader;
    }

    private static boolean printLogInfo(int obj){
        IntBuffer iVal = BufferUtils.createIntBuffer(1);
        ARBShaderObjects.glGetObjectParameterARB(obj,
        ARBShaderObjects.GL_OBJECT_INFO_LOG_LENGTH_ARB, iVal);

        int length = iVal.get();
        if (length > 1) {
            // We have some info we need to output.
            ByteBuffer infoLog = BufferUtils.createByteBuffer(length);
            iVal.flip();
            ARBShaderObjects.glGetInfoLogARB(obj, iVal, infoLog);
            byte[] infoBytes = new byte[length];
            infoLog.get(infoBytes);
            String out = new String(infoBytes);
            System.out.println("Info log:\n"+out);
        }
        else return true;
        return false;
    }

}

这是片段着色器的代码

varying vec4 vertColor;

void main(){
    gl_FragColor = vertColor;
}

和顶点着色器:

varying vec4 vertColor;

void main(){
    gl_Position = gl_ModelViewProjectionMatrix*gl_Vertex;
    vertColor = vec4(0.6, 0.3, 0.4, 1.0);
}

这是我运行代码时得到的输出:

Info log:
Vertex shader was successfully compiled to run on hardware.
Info log:
Fragment shader was successfully compiled to run on hardware.

这是一个屏幕截图:http://dl.dropbox.com/u/28109593/glslss.png

最佳答案

问题是由于您在信息日志中看到了任何内容,即它正在生成一条成功消息,某些 OpenGL 驱动程序倾向于这样做。 printLogInfo 还兼作验证功能,如果有任何日志信息,则返回 false,这告诉 createVertShader 和 createFragShader 将完美的着色器 id 归零并返回失败。这真的不是一个好的设计,出于类似的原因(而且我知道它来自其他人,所以我知道我不会亲自攻击你:)

此程序的快速解决方法只是简单地使 printLogInfo 始终返回 true。您最终需要做的是使用 glGetShader(id, param) 检查返回状态,如下所示:

glCompileShader(obj)
if (glGetShader(obj, GL_COMPILE_STATUS) == GL_FALSE
    ... handle error here ...

然后进行链接和验证:

glLinkProgram(obj)
if (glGetProgram(obj, GL_LINK_STATUS) == GL_FALSE
    ... handle error here ...

glValidateProgram(obj)
if (glGetProgram(obj, GL_VALIDATE_STATUS) == GL_FALSE
    ... handle error here ...

我不知道这些的 ARB_* 等价物,抱歉,但是对于这种基本的东西,您可能应该使用 OpenGL 2.0 API 而不是 ARB 扩展。任何仍然只支持着色器作为扩展的东西可能都不值得使用着色器。

关于java - GLSL LWJGL 问题/着色器无能为力?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8825459/

相关文章:

在 Windows 7 上使用 GLUT 的 OpenGL,全屏模式不显示消息框

opengl - 如果指定了 GL_COLOR_BUFFER_BIT 掩码,glBlitFramebuffer 是否会复制所有颜色附件?

canvas - WebGL 使用不同的混合模式绘制 2d 对象

android - OpenGL阴影贴图移动版不起作用

java - 从按钮和菜单项 JAVA 访问相同的 fragment

java - 您推荐什么 Java XML 库(替换 dom4j)?

java - 在 Spring Boot/执行器根端点上返回 404

java - 更新产品数量后总价不正确

c++ - 如何将 OpenGL 加载到 Visual Studio 2012

math - GLSL |广告牌着色器,保持缩放