ZBLOG

Linux 使用OpenGL 实现一个着色器的例子

下面是一个简单的在Linux上使用OpenGL实现着色器的例子。这个示例展示了如何创建一个窗口,初始化OpenGL,并使用顶点和片段着色器渲染一个三角形。

准备工作

  1. 确保你已经安装了OpenGL、GLM(用于数学计算)和GLEW(用于管理OpenGL扩展)库。如果没有,请使用包管理器进行安装,例如在Ubuntu中可以运行:
   sudo apt-get install libglfw3-dev libglew-dev libglm-dev
  1. 创建一个新的C++源文件,比如main.cpp

示例代码

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <iostream>

// 顶点着色器源码
const char* vertexShaderSource = R"(
#version 330 core
layout(location = 0) in vec3 aPos;
void main() {
    gl_Position = vec4(aPos, 1.0);
}
)";

// 片段着色器源码
const char* fragmentShaderSource = R"(
#version 330 core
out vec4 FragColor;
void main() {
    FragColor = vec4(1.0, 0.5, 0.2, 1.0); // 设置颜色为橙色
}
)";

void checkCompileErrors(GLuint shader, std::string type) {
    int success;
    char infoLog[512];
    if (type != "PROGRAM") {
        glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
        if (!success) {
            glGetShaderInfoLog(shader, 512, NULL, infoLog);
            std::cout << "ERROR::SHADER_COMPILATION_ERROR of type: " << type << "\n"
                      << infoLog << "\n -- --------------------------------------------------- -- " << std::endl;
        }
    } else {
        glGetProgramiv(shader, GL_LINK_STATUS, &success);
        if (!success) {
            glGetProgramInfoLog(shader, 512, NULL, infoLog);
            std::cout << "ERROR::PROGRAM_LINKING_ERROR of type: " << type << "\n"
                      << infoLog << "\n -- --------------------------------------------------- -- " << std::endl;
        }
    }
}

int main() {
    // 初始化 GLFW
    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

    // 创建窗口
    GLFWwindow* window = glfwCreateWindow(800, 600, "Learn OpenGL", nullptr, nullptr);
    if (window == nullptr) {
        std::cerr << "Failed to create GLFW window" << std::endl;
        glfwTerminate();
        return -1;
    }
    
    glfwMakeContextCurrent(window);

    // 初始化 GLEW
    glewExperimental = GL_TRUE; 
    if (glewInit() != GLEW_OK) {
        std::cerr << "Failed to initialize GLEW" << std::endl;
        return -1;
    }

    // 定义三角形的顶点数据
    float vertices[] = {
         0.5f,  0.5f, 0.0f,
         0.5f, -0.5f, 0.0f,
        -0.5f, -0.5f, 0.0f,
         -0.5f , 0.5f , 0.0f 
     };

     unsigned int indices[] = {  
         // 第一部分组成三角形的索引顺序 
          1 ,2 ,3 ,
          // 第二部分组成三角形的索引顺序 
          // 从上到下,逆时针方向,表示第一个三角形由A B C构成第二个由C A D 构成。
          // A -> 第三个点 B -> 第四个点 C -> 第一点 D -> 第二个点  
          

      };


    

   
      
       
     


    

 

     
      
      

   

    

 

 

   

  




     GLuint VBO; 
     GLuint VAO; 
     GLuint EBO;

     glGenVertexArrays(1,&VAO);  
     glGenBuffers(1,&VBO);  
     glGenBuffers(1,&EBO);  
    
     

// 把数组绑定到VAO上面进行操作  
//首先我们要告诉OpenGL我们即将做什么。
// bind the Vertex Array Object first, 然后再设置我们的缓冲并给它们链接。   
   glBindVertexArray(VAO);

   //把顶点数据传输给缓冲对象,将其存储在VBO中。
   glBindBuffer(GL_ARRAY_BUFFER,VBO);    
   glBufferData(GL_ARRAY_BUFFER,sizeof(vertices),vertices , GL_STATIC_DRAW);  


   //
   glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,EBO);    
   glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(indices),indices , GL_STATIC_DRAW);  


   //
   

   
  




      



   

 

      
// 告诉OpenGL如何解释顶点数据,将位置属性链接到 VBO中的每个属性,
      // 对应于 shader 中的位置输入变量aPos。
      
      glVertexAttribPointer(0 ,3 , GL_FLOAT , GL_FALSE ,3 * sizeof(float),(void*)nullptr ); 
    
      ///启用这个属性,以便能够使用它。  
      glEnableVertexAttribArray(0);


     
   
 

   

  




    

   
      
   
    
      

     
  

    
    

    
        

     
        
            
             
    
        
       

         
    


            
        

            
             
        
    
    
     

        
           
       

        
         
          
       
       
       
       

          
    
    
     

// 分别编译我们的顶点和片段着色器。

GLuint vertexShader; 
GLuint fragmentShader; 
GLuint shaderProgram;

// 顶点着色器调用相应函数来完成其编译任务。并检查错误。
vertexShader=glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader ,1 ,&vertexShaderSource,NULL );
glCompileShader(vertexShader );   
checkCompileErrors(vertexShader ,"VERTEX");

// 分别对片段着色器调用相应函数来完成其编译任务。同样需检查错误。
fragmentShader=glCreateShader(GL_FRAGMENT_SHADER); 
glShaderSource(fragmentShader ,1,&fragmentShaderSource,NULL );
glCompileShader(fragmentShader );  
checkCompileErrors(fragmentShader ,"FRAGMENT");

// 将两者链接到同一个程序当中去。
shaderProgram=glCreateProgram(); 
glAttachShader(shaderProgram ,vertexShader );
glAttachShader(shaderProgram ,fragmentShader );
glLinkProgram(shaderProgram );

// 删除不再需要的各单独部件代码(这并不会影响已连接程序)。
glDeleteShader(vertexShader );  
glDeleteShader(fragmentShader );  


// 主循环,直到用户关闭窗口:
while (!glfwWindowShouldClose(window)) {

	// 渲染指令:每次渲染之前清空屏幕内容与颜色信息,使之透明黑黑的状态,然后绘制图像。
	glClearColor(0.2f,.3f,.3f,.9f );	
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

	// 使用创建好的程序:
	glUseProgram(shaderProgram);

	// 绘制三角形:
	glBindVertexArray(VAO);
	glDrawElements(GL_TRIANGLES,sizeof(indices)/sizeof(unsigned int),GL_UNSIGNED_INT,(void*)nullptr );

	// swap前后缓冲,并查询IO事件,触发回调函数:
	glfwSwapBuffers(window);
	glfwPollEvents();
}

// 清理资源:
glDeleteVertexArrays(1,&VAO);
glDeleteBuffers(1,&VBO);

// 最后终止 GLFW:
glfwTerminate();

return 0;

}

编译与运行

使用以下命令编译该代码:

g++ main.cpp -o opengl_example -lGLEW -lGLFW -lGL

然后运行生成的可执行文件:

./opengl_example

总结

以上代码创建了一个基本的OpenGL应用程序,通过使用顶点和片段着色器来绘制一个橙色的三角形。你可以根据需要修改顶点数据或着色器代码以进行更多实验。确保你的环境中有合适版本的OpenGL驱动程序,并且库正确安装。在开发过程中,可以通过打印日志或添加调试信息来帮助解决可能出现的问题。


内容由零声教学AI助手提供,问题来源于学员提问

本站部分文章来源于网络,版权归原作者所有,如有侵权请联系站长删除。
转载请注明出处:https://sdn.0voice.com/?id=6608

分享:
扫描分享到社交APP
上一篇
下一篇
发表列表
游客 游客
此处应有掌声~
评论列表

还没有评论,快来说点什么吧~

联系我们

在线咨询: 点击这里给我发消息

微信号:3007537140

上班时间: 10:30-22:30

关注我们
x

注册

已经有帐号?