首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

GLSL 著色器入門:C 語言 OpenGL 繪製變色三角形

     編輯:關於C語言

著色器代碼

Vertex Shader (basic.vert)


#version 400
layout(location = 0) in vec3 VertexPosition;
layout(location = 1) in vec3 VertexColor;
out vec3 Color;
uniform mat4 Matrix;
void main() {
    Color = VertexColor;
    gl_Position = Matrix * vec4(VertexPosition, 1.0);
}

Fragment Shader (basic.frag)


#version 400
in vec3 Color;
out vec4 FragColor;
void main() {
    FragColor = vec4(Color, 1.0);
}

C 主程式 (main.c)


#include <stdio.h>
#include <stdlib.h>
#include <GL/glew.h>
#include <GL/freeglut.h>
#include "readtext.h" // 自訂著色器讀取工具

GLuint vShader, fShader, programHandle;
GLuint vaoHandle, vboHandles[2];
float positionData[] = { -1.0f, -1.0f, 0.0f,  1.0f, -1.0f, 0.0f,  0.0f, 1.0f, 0.0f };
float colorData[]    = {  0.2f,  0.8f, 0.0f,  0.4f,  0.6f, 0.0f,  0.1f,  0.9f, 1.0f };
float matrix[16] = {
    0.5f, 0.0f, -0.866f, 0.0f,
    0.0f, 1.0f,  0.0f,   0.0f,
    0.866f, 0.0f,  0.5f,   0.0f,
    0.0f, 0.0f,  0.0f,   1.0f
}; // Y 軸旋轉 60 度矩陣

void initShader() {
    glewInit();
    // 編譯 Vertex Shader
    vShader = glCreateShader(GL_VERTEX_SHADER);
    char *vs = readText("basic.vert");
    glShaderSource(vShader, 1, (const char**)&vs, NULL);
    glCompileShader(vShader);
    free(vs);
    // 檢查編譯錯誤...
    // 編譯 Fragment Shader (同理)
    // 連結程式
    programHandle = glCreateProgram();
    glAttachShader(programHandle, vShader);
    glAttachShader(programHandle, fShader);
    glLinkProgram(programHandle);
    glUseProgram(programHandle);
}

void initVBO() {
    glGenBuffers(2, vboHandles);
    glBindBuffer(GL_ARRAY_BUFFER, vboHandles[0]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(positionData), positionData, GL_STATIC_DRAW);
    glBindBuffer(GL_ARRAY_BUFFER, vboHandles[1]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(colorData), colorData, GL_STATIC_DRAW);

    glGenVertexArrays(1, &vaoHandle);
    glBindVertexArray(vaoHandle);
    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);
    glBindBuffer(GL_ARRAY_BUFFER, vboHandles[0]);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
    glBindBuffer(GL_ARRAY_BUFFER, vboHandles[1]);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, NULL);
}

void display() {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glBindVertexArray(vaoHandle);
    glDrawArrays(GL_TRIANGLES, 0, 3);
    glBindVertexArray(0);

    // 傳遞矩陣 uniform
    GLint loc = glGetUniformLocation(programHandle, "Matrix");
    glUniformMatrix4fv(loc, 1, GL_TRUE, matrix);

    glutSwapBuffers();
    glutPostRedisplay();
}

int main(int argc, char **argv) {
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
    glutInitWindowSize(600, 600);
    glutCreateWindow("GLSL Triangle");
    initShader();
    initVBO();
    glClearColor(0.0, 0.0, 0.0, 1.0);
    glutDisplayFunc(display);
    glutMainLoop();
    return 0;
}

編譯鏈結


gcc main.c readtext.c -o triangle -lGLEW -lGL -lglut -lGLU -lm
# 需安裝 freeglut3-dev, libglew-dev

關鍵概念

  • VAO (Vertex Array Object):封裝 VBO 綁定狀態與屬性指標配置,切換繪製物件只需綁定 VAO。
  • VBO (Vertex Buffer Object):顯存緩衝區儲存頂點屬性 (位置、顏色、法線、UV)。
  • Uniform:著色器只讀常數 (矩陣、時間、材質參數),CPU 透過 glUniform* 更新。
  • Attribute:頂點輸入屬性 (位置、顏色),對應 layout(location=N)。
  • GLSL 版本:#version 400 要求 OpenGL 4.0+,舊硬體可用 #version 330 或 #version 130。

常見問題

現象原因與解決
黑屏/無輸出著色器編譯/連結失敗 → 必須檢查 glGetShaderInfoLog/glGetProgramInfoLog
顏色錯誤Attribute 位置不匹配 → 確認 layout(location) 與 glVertexAttribPointer index 一致
矩陣不生效Uniform 位置 -1 → 名稱拼寫錯誤或著色器優化移除未使用 uniform
GLEW 初始化失敗須在 glutCreateWindow 後呼叫 glewInit()
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved