繁体   English   中英

LWJGL - 顶点/片段着色器不工作

[英]LWJGL - Vertex / Fragment Shader not working

我设法打开了一个 window 并在 LWJGL 的屏幕上渲染了一个三角形。 我现在为顶点着色器和片段着色器创建了两个外部文件。 然而,三角形仍然是白色的。

这是主文件,它调用加载顶点着色器并编译它的方法,我添加了一个简单的 system.out 行来查看它是否被调用,它是。

import org.lwjgl.*;
import org.lwjgl.glfw.*;
import org.lwjgl.opengl.*;
import org.lwjgl.system.*;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.nio.*;

import static org.lwjgl.glfw.Callbacks.*;
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.system.MemoryStack.*;
import static org.lwjgl.system.MemoryUtil.*;

public class Main {
    
     String TITLE = "f";
    
    

    // The window handle
    private long window;

    public void run() {
        System.out.println("Hello LWJGL " + Version.getVersion() + "!");

        init();
        loop();

        // Free the window callbacks and destroy the window
        glfwFreeCallbacks(window);
        glfwDestroyWindow(window);

        // Terminate GLFW and free the error callback
        glfwTerminate();
        glfwSetErrorCallback(null).free();
    }

    private void init() {
        // Setup an error callback. The default implementation
        // will print the error message in System.err.
        GLFWErrorCallback.createPrint(System.err).set();

        // Initialize GLFW. Most GLFW functions will not work before doing this.
        if ( !glfwInit() )
            throw new IllegalStateException("Unable to initialize GLFW");

        // Configure GLFW
        glfwDefaultWindowHints(); // optional, the current window hints are already the default
        glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); // the window will stay hidden after creation
        glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); // the window will be resizable

        // Create the window
        window = glfwCreateWindow(300, 300, TITLE, NULL, NULL);
        if ( window == NULL )
            throw new RuntimeException("Failed to create the GLFW window");

        // Setup a key callback. It will be called every time a key is pressed, repeated or released.
        glfwSetKeyCallback(window, (window, key, scancode, action, mods) -> {
            if ( key == GLFW_KEY_ESCAPE && action == GLFW_RELEASE )
                glfwSetWindowShouldClose(window, true); // We will detect this in the rendering loop
        });

        // Get the thread stack and push a new frame
        try ( MemoryStack stack = stackPush() ) {
            IntBuffer pWidth = stack.mallocInt(1); // int*
            IntBuffer pHeight = stack.mallocInt(1); // int*

            // Get the window size passed to glfwCreateWindow
            glfwGetWindowSize(window, pWidth, pHeight);

            // Get the resolution of the primary monitor
            GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor());

            // Center the window
            glfwSetWindowPos(
                window,
                (vidmode.width() - pWidth.get(0)) / 2,
                (vidmode.height() - pHeight.get(0)) / 2
            );
        } // the stack frame is popped automatically

        // Make the OpenGL context current
        glfwMakeContextCurrent(window);
    
        
        // Enable v-sync
        glfwSwapInterval(1);
    
        // Make the window visible
        glfwShowWindow(window);
        
    }

    private void loop() {
        // This line is critical for LWJGL's interoperation with GLFW's
        // OpenGL context, or any context that is managed externally.
        // LWJGL detects the context that is current in the current thread,
        // creates the GLCapabilities instance and makes the OpenGL
        // bindings available for use.
        GL.createCapabilities();
        
        drawTriangle();
        loadShader("screenvertfilelocation", GL30.GL_VERTEX_SHADER);
        loadShader("screenvertfilelocation", GL30.GL_FRAGMENT_SHADER);
        
        
        
        // Set the clear color
        glClearColor(1.0f, 0.0f, 0.0f, 0.0f);

        // Run the rendering loop until the user has attempted to close
        // the window or has pressed the ESCAPE key.
        while ( !glfwWindowShouldClose(window) ) {
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear the framebuffer
            
            processTriangle();

            glfwSwapBuffers(window); // swap the color buffers

            // Poll for window events. The key callback above will only be
            // invoked during this call.
            glfwPollEvents();
        }
    }

    public static void main(String[] args) {
        new Main().run();
    }
    
    int vertexCount = 0;
    int VAO = 0;
    int VBO = 0;

    public void drawTriangle() {
    
    float vertices[] = {
            -0.5f, -0.5f, 0.0f,
             0.5f, -0.5f, 0.0f,
             0.0f,  0.5f, 0.0f
        };  


    int VBO = GL30.glGenBuffers();
    int VAO = GL30.glGenBuffers();
 
    
    // Sending data to OpenGL requires the usage of (flipped) byte buffers
    FloatBuffer verticesBuffer = BufferUtils.createFloatBuffer(vertices.length);
    verticesBuffer.put(vertices);
    verticesBuffer.flip();
     
    vertexCount = 3;
    
    
    GL30.glBindVertexArray(VAO);

    GL30.glBindBuffer(GL30.GL_ARRAY_BUFFER, VBO);

    GL30.glBufferData(GL30.GL_ARRAY_BUFFER, verticesBuffer, GL30.GL_STATIC_DRAW);
    

    GL30.glVertexAttribPointer(0, 3, GL30.GL_FLOAT, false, 0, 0);
    
    GL30.glEnableVertexAttribArray(0);
    
    GL30.glBindBuffer(GL30.GL_ARRAY_BUFFER, 0); 
    GL30.glBindVertexArray(0); 
    
    }
    
    public void processTriangle() {
        GL30.glBindVertexArray(VAO);
        GL30.glDrawArrays(GL_TRIANGLES, 0, 3);
    }
    
    
    //Deals with the Shaders
    private static int loadShader(String file, int type){
          StringBuilder shaderSource = new StringBuilder();
          try{
           BufferedReader reader = new BufferedReader(new FileReader(file));
           String line;
           while((line = reader.readLine())!=null){
            shaderSource.append(line).append("//\n");
           }
           reader.close();
          }catch(IOException e){
           e.printStackTrace();
           System.exit(-1);
          }
          int shaderID = GL20.glCreateShader(type);
          GL20.glShaderSource(shaderID, shaderSource);
          GL20.glCompileShader(shaderID);
          
          int vertexShader;
          vertexShader = GL30.glCreateShader(GL30.GL_VERTEX_SHADER);
          int fragmentShader;
          fragmentShader = GL30.glCreateShader(GL30.GL_FRAGMENT_SHADER);
          
          
          
          
          int shaderProgram;
          shaderProgram = GL30.glCreateProgram();
          
          
          GL30.glAttachShader(shaderProgram, vertexShader);
          GL30. glAttachShader(shaderProgram, fragmentShader);
          GL30.glLinkProgram(shaderProgram);
         
         
          GL30.glUseProgram(shaderProgram);
          
         GL30.glDeleteShader(vertexShader);
         GL30.glDeleteShader(fragmentShader); 
          
          System.out.println("Hello");
          
          if(GL20.glGetShaderi(shaderID, GL20.GL_COMPILE_STATUS )== GL11.GL_FALSE){
           System.out.println(GL20.glGetShaderInfoLog(shaderID, 500));
           System.err.println("Could not compile shader!");
           System.exit(-1);
          }
          return shaderID;
         }

}

这是顶点着色器文件:

    #version 330 core
layout (location = 0) in vec3 aPos; 
  
out vec4 vertexColor; 

void main()
{
    gl_Position = vec4(aPos, 1.0); 
    vertexColor = vec4(0.5, 4.0, 0.0, 1.0); 
}

这是片段着色器文件:

    #version 330 core
out vec4 FragColor;
  
in vec4 vertexColor; 

void main()
{
    FragColor = vertexColor;
} 

这里有改进和更正

1. 改进

这是在你的着色器中。 链接着色器后,您还需要验证它。 尽管您的着色器在没有它的情况下可以很好地用于更复杂的程序,但它可以揭示隐藏的错误

这是修改后的代码[如果你愿意,只是一个建议]

private void loadProgram()
{
      int vertex,fragment;
     
      int programID=GL20.glCreateProgram();  //Step 1 create program and attach source code to it
      GL20.glAttachShader(programID,vertex=loadShader("screenvertfilelocation",GL20.GL_VERTEX_SHADER));
      GL20.glAttachShader(programID,fragment=loadShader("screenvertfilelocation",GL20.GL_FRAGMENT_SHADER));
      
      
      
      GL20.glLinkProgram(programID);   //Step 2 link the program
      if(GL20.glGetProgrami(programID,GL20.GL_LINK_STATUS)==GL11.GL_FALSE)
      {  
        int infoLogSize=GL20.glGetProgrami(programID,GL20.GL_INFO_LOG_LENGTH); //Get's exact error size rather than using 500
        System.err.println(GL20.glGetProgramInfoLog(programID,infoLogSize));
        System.err.println("COULD NOT LINK SHADER");
        System.exit(-1);
      } 
      
      
      
      GL20.glValidateProgram(programID);  //Step 3 Validate shader
      if(GL20.glGetProgrami(programID,GL20.GL_VALIDATE_STATUS)==GL11.GL_FALSE)
      {
        int infoLogSize=GL20.glGetProgrami(programID,GL20.GL_INFO_LOG_LENGTH);  //Get exact error size
        System.err.println(GL20.glGetProgramInfoLog(programID,infoLogSize));
        System.err.println("COULD NOT VALIDATE SHADER");
        System.exit(-1);
      } 
      
      GL20.glDeleteShader(vertex);    //Step 4 clean up
      GL20.glDeleteShader(fragment);
      
      GL20.glUseProgram(programID);
    }
    
    private int loadShader(String fileName,int shaderType)
    {
     try(BufferedReader reader = new BufferedReader(new FileReader(fileName)))
     {
      StringBuilder source=new StringBuilder();
      
      String line;
      while((line=reader.readLine())!=null)
      {
       source.append(line)
             .append(System.lineSeparator());
      }
      
      int shaderID=GL20.glCreateShader(shaderType);
      GL20.glShaderSource(shaderID,source);
      GL20.glCompileShader(shaderID);

      if(GL20.glGetShaderi(shaderID,GL20.GL_COMPILE_STATUS)==GL11.GL_FALSE)
      {
        int infoLogSize=GL20.glGetShaderi(shaderID,GL20.GL_INFO_LOG_LENGTH); 
        throw new IOException("COULD NOT COMPILE SHADER "+GL20.glGetShaderInfoLog(shaderID,infoLogSize));
      }    
      return shaderID;
     }
     catch(IOException ex)
     {
      ex.printStackTrace(System.err);
      System.exit(-1);
      return -1;
     }  
    }  

在 drawTriangle() 之后调用 loadProgram()

2. 你的解决方案

这只是@Rabbid76 帖子的后续跟进

一旦我将您的代码复制粘贴到我的 IDE 中,我就会收到警告

local variable hides a field

在这段代码中

int vertexCount = 0;
    int VAO = 0;
    int VBO = 0;

    public void drawTriangle() {
    
    float vertices[] = 
     {
            -0.5f, -0.5f, 0.0f,
             0.5f, -0.5f, 0.0f,
             0.0f,  0.5f, 0.0f
   };  

    //The warning here. You are redeclaring VBO & VAO
    int VBO = GL15.glGenBuffers();
    int VAO = GL30.glGenVertexArrays(); // @Rabbid76 original fix

只需删除声明

    VBO = GL15.glGenBuffers();
    VAO = GL30.glGenVertexArrays();

我正在使用 LWJGL 3.1.3 并且我使用的大多数 gl 函数和常量属于不同的 gl 版本,例如没有

GL30.GL_FLOAT

GL11.GL_FLOAT

仅举几个

Output:

在此处输入图像描述

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM