首页 > 其他分享 >OpenGL 和 GLSL 在顶点着色器中动态调整裁剪平面参数的简单代码示例

OpenGL 和 GLSL 在顶点着色器中动态调整裁剪平面参数的简单代码示例

时间:2024-11-10 16:19:17浏览次数:1  
标签:GLSL 1.0 OpenGL 裁剪 示例 vec4 fragPosition GL 着色器

以下是一个使用 OpenGL 和 GLSL 在顶点着色器中动态调整裁剪平面参数的简单代码示例:

// OpenGL 初始化代码
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>

GLFWwindow* window;

// 初始化 GLFW
void initGLFW() {
    if (!glfwInit()) {
        std::cerr << "Failed to initialize GLFW" << std::endl;
        exit(EXIT_FAILURE);
    }

    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

    window = glfwCreateWindow(800, 600, "Dynamic Clip Plane Example", nullptr, nullptr);
    if (!window) {
        std::cerr << "Failed to create GLFW window" << std::endl;
        glfwTerminate();
        exit(EXIT_FAILURE);
    }

    glfwMakeContextCurrent(window);
}

// 初始化 GLEW
void initGLEW() {
    glewExperimental = GL_TRUE;
    if (glewInit()!= GLEW_OK) {
        std::cerr << "Failed to initialize GLEW" << std::endl;
        glfwTerminate();
        exit(EXIT_FAILURE);
    }
}
// 顶点着色器代码
#version 330 core

layout (location = 0) in vec3 position;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
uniform vec4 clipPlane; // 裁剪平面参数

out vec3 fragPosition;

void main() {
    fragPosition = vec3(model * vec4(position, 1.0));
    // 计算顶点到裁剪平面的距离
    float distance = dot(vec4(fragPosition, 1.0), clipPlane);
    // 如果顶点在裁剪平面背面,则将其位置设置为一个无效值(这里简单设置为很大的负值)
    if (distance < 0.0) {
        gl_Position = vec4(-10000.0, -10000.0, -10000.0, 1.0);
    } else {
        gl_Position = projection * view * model * vec4(position, 1.0);
    }
}
// 片段着色器代码
#version 330 core

in vec3 fragPosition;
out vec4 color;

void main() {
    color = vec4(fragPosition, 1.0);
}
// 渲染循环函数
void renderLoop() {
    while (!glfwWindowShouldClose(window)) {
        // 处理输入
        glfwPollEvents();

        // 动态更新裁剪平面参数(这里只是简单的示例,你可以根据实际需求更新)
        float clipPlaneParameters[4] = {0.5, 0.5, -0.5, -0.5};
        glUniform4fv(glGetUniformLocation(yourShaderProgram, "clipPlane"), 1, clipPlaneParameters);

        // 清除颜色和深度缓冲区
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        // 使用你的着色器程序进行渲染
        glUseProgram(yourShaderProgram);

        // 绘制物体(这里假设你已经有了一个简单的物体绘制代码)
        // 例如:绘制一个三角形
        GLfloat vertices[] = {
            0.0f, 0.5f, 0.0f,
            -0.5f, -0.5f, 0.0f,
            0.5f, -0.5f, 0.0f
        };

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

        glBindVertexArray(VAO);
        glBindBuffer(GL_ARRAY_BUFFER, VBO);
        glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (void*)0);
        glEnableVertexAttribArray(0);

        glDrawArrays(GL_TRIANGLES, 0, 3);

        glBindVertexArray(0);
        glDeleteBuffers(1, &VBO);
        glDeleteVertexArrays(1, &VAO);

        // 交换前后缓冲区
        glfwSwapBuffers(window);
    }
}
// 主函数
int main() {
    initGLFW();
    initGLEW();

    // 编译和链接着色器程序
    GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
    GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);

    const char* vertexShaderSource = R"(
        #version 330 core

        layout (location = 0) in vec3 position;

        uniform mat4 model;
        uniform mat4 view;
        uniform mat4 projection;
        uniform vec4 clipPlane;

        out vec3 fragPosition;

        void main() {
            fragPosition = vec3(model * vec4(position, 1.0));
            float distance = dot(vec4(fragPosition, 1.0), clipPlane);
            if (distance < 0.0) {
                gl_Position = vec4(-10000.0, -10000.0, -10000.0, 1.0);
            } else {
                gl_Position = projection * view * model * vec4(position, 1.0);
            }
        }
    )";

    const char* fragmentShaderSource = R"(
        #version 330 core

        in vec3 fragPosition;
        out vec4 color;

        void main() {
            color = vec4(fragPosition, 1.0);
        }
    )";

    glShaderSource(vertexShader, 1, &vertexShaderSource, nullptr);
    glCompileShader(vertexShader);

    // 检查顶点着色器编译错误
    GLint success;
    GLchar infoLog[512];
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
    if (!success) {
        glGetShaderInfoLog(vertexShader, 512, nullptr, infoLog);
        std::cerr << "Vertex Shader Compilation Failed: " << infoLog << std::endl;
        glfwTerminate();
        return -1;
    }

    glShaderSource(fragmentShader, 1, &fragmentShaderSource, nullptr);
    glCompileShader(fragmentShader);

    // 检查片段着色器编译错误
    glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
    if (!success) {
        glGetShaderInfoLog(fragmentShader, 512, nullptr, infoLog);
        std::cerr << "Fragment Shader Compilation Failed: " << infoLog << std::endl;
        glfwTerminate();
        return -1;
    }

    GLuint shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);
    glLinkProgram(shaderProgram);

    // 检查着色器程序链接错误
    glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
    if (!success) {
        glGetProgramInfoLog(shaderProgram, 512, nullptr, infoLog);
        std::cerr << "Shader Program Linking Failed: " << infoLog << std::endl;
        glfwTerminate();
        return -1;
    }

    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);

    // 设置你的着色器程序
    glUseProgram(shaderProgram);

    // 获取 uniform 变量的位置
    GLint modelLoc = glGetUniformLocation(shaderProgram, "model");
    GLint viewLoc = glGetUniformLocation(shaderProgram, "view");
    GLint projectionLoc = glGetUniformLocation(shaderProgram, "projection");

    // 设置模型、视图和投影矩阵(这里只是简单的示例矩阵,你需要根据实际情况设置)
    glm::mat4 modelMatrix = glm::mat4(1.0f);
    glm::mat4 viewMatrix = glm::lookAt(glm::vec3(0.0f, 0.0f, 3.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
    glm::mat4 projectionMatrix = glm::perspective(glm::radians(45.0f), 800.0f / 600.0f, 0.1f, 100.0f);

    glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(modelMatrix));
    glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(viewMatrix));
    glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, glm::value_ptr(projectionMatrix));

    // 进入渲染循环
    renderLoop();

    // 清理资源
    glfwTerminate();
    return 0;
}

在上述代码中:

  1. 首先初始化 GLFWGLEW,创建一个 OpenGL 窗口。
  2. 在顶点着色器中,定义了一个 uniform 变量 clipPlane 来接收裁剪平面的参数。在 main 函数中,计算每个顶点到裁剪平面的距离,如果顶点在裁剪平面背面,则将其位置设置为一个无效值,使其在渲染时被裁剪掉。
  3. 在片段着色器中,简单地将顶点位置作为颜色输出,以便在屏幕上显示。
  4. renderLoop 函数中,动态更新裁剪平面参数,并进行渲染操作。

请注意,上述代码只是一个简单的示例,实际应用中你需要根据具体需求进一步完善和扩展代码,例如处理更多的输入、加载模型数据等。并且确保你的 OpenGL 环境已经正确配置,并且支持 GLSL 的相关特性。

标签:GLSL,1.0,OpenGL,裁剪,示例,vec4,fragPosition,GL,着色器
From: https://www.cnblogs.com/DesertCactus/p/18538137

相关文章

  • GPU OpenGL 管线
    GPUOpenGL管线主要分为以下几个阶段:顶点数据输入:数据定义与准备:开发者定义要渲染的图形的顶点数据,这些数据包含了每个顶点的位置、颜色、纹理坐标、法线向量等信息。例如,对于一个简单的三角形,需要指定三个顶点的三维坐标以及相关属性。这些数据通常存储在内存中,可以通过数组......
  • 在OpenGL中实现视角切换插值过渡动画
    在OpenGL中实现视角切换插值过渡动画可以通过以下步骤来完成:一、定义视角结构体首先,需要定义一个结构体来表示视角相关的信息,通常包括观察位置(EyePosition)、观察目标点(LookAtPoint)和上方向向量(UpVector)。例如:structCamera{glm::vec3eye;glm::vec3center;......
  • 基于KD树、包围盒与RayCast(射线投射)实现物体拾取的示例代码框架
    以下是一个基于KD树、包围盒与RayCast(射线投射)实现物体拾取的示例代码框架及相关解释。这个示例假设是在一个三维空间场景下进行操作,主要目的是通过从指定视点发出射线,利用KD树对场景中的物体包围盒进行组织和快速搜索,来判断射线与哪个物体相交,从而实现物体的拾取。#include<ios......
  • OpenGL 纹理采样 在GPU中哪个部件完成
    OpenGL纹理采样主要在GPU的流式多处理器(StreamingMultiprocessor,SM)中完成。SM内部包含多个用于执行计算的核心(Core)以及纹理缓存(TextureCache)等部件,这些部件协同工作来实现纹理采样。具体过程如下:纹理数据获取:当需要进行纹理采样时,首先会从纹理内存(通常是显存中的一块区......
  • 用GLSL 和 GLM 实现OpenGL trackball
    以下是一个使用GLSL(OpenGLShadingLanguage)和GLM(OpenGLMathematics)库来实现OpenGLtrackball功能的示例。这个示例将展示如何通过鼠标操作来旋转场景中的物体,就像在操作一个虚拟的轨迹球一样。1.准备工作包含必要的头文件和库:需要包含GLFW头文件用于创建窗口和处理事件,GLA......
  • OpenGL 如何实现 trackball
    在OpenGL中实现trackball(轨迹球)功能可以让用户通过鼠标操作来旋转场景中的物体,就好像在操作一个虚拟的轨迹球一样。以下是一种常见的实现方式的步骤:基本原理Trackball的基本思想是将二维的鼠标移动映射到三维空间中的旋转操作。当用户在屏幕上按下鼠标并移动时,根据鼠标的起......
  • devc++配置opengl库
    由于VisualStudio太占内存,所以用老古董devc++配图形学的环境。用到的文件下载链接Step1:建项目首先打开dev点文件--新建--项目--Multimedia--OpenGLc++/c都行(我这里用的c++)名称最好用英文,然后确定,保存的地方也最好没有中文路径Step2:添加库文件找到DEV-C++的安装目录(右键......
  • Air780E软件指南:UDP应用示例
    一、UDP概述UDP(用户数据报协议,UserDatagramProtocol)是一种无连接的、不可靠的传输层协议,主要用于实现网络中的快速通讯。以下是UDP通讯的主要特点:1.1无连接通讯:UDP在发送数据之前不需要建立连接,这大大减少了通讯的延迟。发送方只需将数据包封装成UDP报文,并附上目的地址......
  • 来了,超全MQTT实用示例
    Air201快速入门之MQTT示例合宙Air201资产定位模组——是一个集成超低功耗4G通信、语音通话、超低功耗定位、计步、震动、Type-C、充电、放音、录音等功能的超小PCBA。内部集成高效、简单、可靠的LuatOS语言,旨在帮助客户降低开发难度,降低研发成本,以及打造超小超低功......
  • Air780E软件指南:zlib解压示例
    一、ZLIB解压工具简介Zlib解压工具是一个广泛使用的压缩和解压缩库,主要用于处理数据的压缩和解压缩任务。Zlib使用的是DEFLATE算法,这是一种通用的压缩算法。它被应用在很多场景中,比如压缩文件、网络传输中的数据压缩、以及各种应用程序中的数据存储和读取。Zlib的代码库相......