opengl基础学习 1

学习范围

OpenGL是一个强大的跨平台图形API,用于渲染2D和3D图形。以下是OpenGL基础学习的关键点和步骤:

1. 基本概念

   - 了解图形渲染管线

   - 熟悉顶点、片段、纹理等基本概念

   - 理解坐标系统(世界坐标、视图坐标、裁剪坐标等)

2. 环境设置

   - 安装OpenGL库和相关工具(如GLFW, GLEW)

   - 配置开发环境(IDE, 编译器等)

3. 创建窗口和OpenGL上下文

   ```cpp

   glfwInit();

   GLFWwindow* window = glfwCreateWindow(800, 600, "OpenGL Window", NULL, NULL);

   glfwMakeContextCurrent(window);

   ```

4. 基本图形绘制

   - 学习如何绘制基本图形(点、线、三角形)

   - 理解和使用顶点缓冲对象(VBO)

   ```cpp

   float vertices[] = {

       -0.5f, -0.5f, 0.0f,

        0.5f, -0.5f, 0.0f,

        0.0f,  0.5f, 0.0f

   };

   

   unsigned int VBO;

   glGenBuffers(1, &VBO);

   glBindBuffer(GL_ARRAY_BUFFER, VBO);

   glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

   ```

5. 着色器编程

   - 学习GLSL(OpenGL着色语言)

   - 编写和使用简单的顶点着色器和片段着色器

   ```glsl

   // 顶点着色器

   #version 330 core

   layout (location = 0) in vec3 aPos;

   void main()

   {

       gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);

   }

   // 片段着色器

   #version 330 core

   out vec4 FragColor;

   void main()

   {

       FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);

   }

   ```

6. 变换

   - 学习矩阵变换(平移、旋转、缩放)

   - 使用数学库(如GLM)进行矩阵运算

7. 纹理

   - 学习如何加载和应用纹理

   - 理解纹理坐标和纹理过滤

8. 摄像机

   - 实现基本的摄像机系统

   - 理解视图矩阵和投影矩阵

9. 光照

   - 学习基本光照模型(如Phong光照模型)

   - 实现环境光、漫反射和镜面反射

10. 高级主题

    - 深度测试和模板测试

    - 混合

    - 帧缓冲

    - 立方体贴图和天空盒

11. 实践项目

    - 创建简单的3D场景

    - 实现基本的交互功能

12. 学习资源

    - OpenGL官方文档

    - LearnOpenGL网站

    - OpenGL编程指南(红皮书)

学习OpenGL是一个循序渐进的过程。从基础概念开始,逐步构建复杂的渲染技术。实践和实验是掌握OpenGL的关键。随着你的进步,你将能够创建越来越复杂和令人印象深刻的图形应用程序。

当然,我很高兴继续深入探讨OpenGL的学习。以下是一些更深入的主题和技巧,可以帮助你进一步提升OpenGL技能:

13. 高级着色器技术

    - 几何着色器的使用

    - 曲面细分着色器

    - 计算着色器的应用

    ```glsl

    // 简单的几何着色器示例

    #version 330 core

    layout (triangles) in;

    layout (line_strip, max_vertices = 6) out;

    void main() {    

        for(int i = 0; i < 3; i++)

        {

            gl_Position = gl_in[i].gl_Position;

            EmitVertex();

            gl_Position = gl_in[i].gl_Position + vec4(0.0, 0.1, 0.0, 0.0);

            EmitVertex();

            EndPrimitive();

        }

    }

    ```

14. 高级渲染技术

    - 延迟渲染(Deferred Rendering)

    - 基于物理的渲染(PBR)

    - 体积渲染

15. 阴影技术

    - 阴影映射(Shadow Mapping)

    - 点光源阴影

    - 级联阴影映射(Cascaded Shadow Maps)

16. 粒子系统

    - GPU加速的粒子模拟

    - 使用变换反馈(Transform Feedback)实现粒子系统

17. 后处理效果

    - 泛光(Bloom)

    - 运动模糊(Motion Blur)

    - 景深(Depth of Field)

18. 优化技术

    - 实例化渲染(Instanced Rendering)

    - 遮挡剔除(Occlusion Culling)

    - 层级细节(LOD)技术

    ```cpp

    // 实例化渲染示例

    glDrawArraysInstanced(GL_TRIANGLES, 0, 36, 100);

    ```

19. 高级纹理技术

    - 法线贴图(Normal Mapping)

    - 视差贴图(Parallax Mapping)

    - HDR纹理

20. 地形渲染

    - 高度图(Heightmap)技术

    - 四叉树(Quadtree)优化

    - 程序化地形生成

21. 水体模拟

    - 水面反射和折射

    - 波浪模拟

    - 因果效应(Caustics)

22. 高级动画技术

    - 骨骼动画

    - 蒙皮技术

    - 反向运动学(Inverse Kinematics)

23. 体积光照和大气散射

    - 体积光(Volumetric Lighting)

    - 大气散射模拟

24. 图形API互操作

    - OpenGL与Vulkan的比较和互操作

    - OpenGL ES的特殊考虑

25. 虚拟现实(VR)和增强现实(AR)

    - 立体渲染技术

    - 头部追踪和空间音频

26. 实时全局光照

    - 光线追踪技术在OpenGL中的应用

    - 辐射度(Radiosity)技术

27. 性能调优和调试

    - 使用GPU分析工具

    - OpenGL调试扩展的应用

28. 跨平台开发

    - 处理不同平台的OpenGL特性差异

    - 移动平台的特殊优化

29. 与其他库的集成

    - 物理引擎集成(如Bullet Physics)

    - 音频库集成(如OpenAL)

30. 高级项目实践

    - 开发一个简单的游戏引擎

    - 创建一个科学可视化应用

初级举例

1. 顶点数组对象(VAO)和顶点缓冲对象(VBO)的使用

```cpp

// 顶点数据

float vertices[] = {

    -0.5f, -0.5f, 0.0f,

     0.5f, -0.5f, 0.0f,

     0.0f,  0.5f, 0.0f

};

unsigned int VAO, VBO;

glGenVertexArrays(1, &VAO);

glGenBuffers(1, &VBO);

// 绑定VAO

glBindVertexArray(VAO);

// 绑定并填充VBO

glBindBuffer(GL_ARRAY_BUFFER, VBO);

glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

// 设置顶点属性指针

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

glEnableVertexAttribArray(0);

// 解绑

glBindBuffer(GL_ARRAY_BUFFER, 0);

glBindVertexArray(0);

```

2. 简单的着色器程序

```cpp

const char *vertexShaderSource = "#version 330 core\n"

    "layout (location = 0) in vec3 aPos;\n"

    "void main()\n"

    "{\n"

    "   gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"

    "}\0";

const char *fragmentShaderSource = "#version 330 core\n"

    "out vec4 FragColor;\n"

    "void main()\n"

    "{\n"

    "   FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"

    "}\n\0";

// 编译着色器

unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER);

glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);

glCompileShader(vertexShader);

unsigned int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);

glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);

glCompileShader(fragmentShader);

// 链接着色器程序

unsigned int shaderProgram = glCreateProgram();

glAttachShader(shaderProgram, vertexShader);

glAttachShader(shaderProgram, fragmentShader);

glLinkProgram(shaderProgram);

// 使用着色器程序

glUseProgram(shaderProgram);

// 清理

glDeleteShader(vertexShader);

glDeleteShader(fragmentShader);

```

3. 纹理加载和使用

```cpp

unsigned int texture;

glGenTextures(1, &texture);

glBindTexture(GL_TEXTURE_2D, texture);

// 设置纹理参数

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

// 加载图像

int width, height, nrChannels;

unsigned char *data = stbi_load("texture.jpg", &width, &height, &nrChannels, 0);

if (data)

{

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);

    glGenerateMipmap(GL_TEXTURE_2D);

}

stbi_image_free(data);

```

4. 变换矩阵的应用

```cpp

#include <glm/glm.hpp>

#include <glm/gtc/matrix_transform.hpp>

#include <glm/gtc/type_ptr.hpp>

// 创建变换矩阵

glm::mat4 trans = glm::mat4(1.0f);

trans = glm::rotate(trans, glm::radians(90.0f), glm::vec3(0.0, 0.0, 1.0));

trans = glm::scale(trans, glm::vec3(0.5, 0.5, 0.5));

// 在着色器中使用

unsigned int transformLoc = glGetUniformLocation(shaderProgram, "transform");

glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(trans));

```

5. 简单的光照模型

顶点着色器:

```glsl

#version 330 core

layout (location = 0) in vec3 aPos;

layout (location = 1) in vec3 aNormal;

uniform mat4 model;

uniform mat4 view;

uniform mat4 projection;

out vec3 Normal;

out vec3 FragPos;

void main()

{

    FragPos = vec3(model * vec4(aPos, 1.0));

    Normal = mat3(transpose(inverse(model))) * aNormal;  

    

    gl_Position = projection * view * vec4(FragPos, 1.0);

}

```

片段着色器:

```glsl

#version 330 core

out vec4 FragColor;

in vec3 Normal;  

in vec3 FragPos;  

  

uniform vec3 lightPos;

uniform vec3 viewPos;

uniform vec3 lightColor;

uniform vec3 objectColor;

void main()

{

    // ambient

    float ambientStrength = 0.1;

    vec3 ambient = ambientStrength * lightColor;

  

    // diffuse

    vec3 norm = normalize(Normal);

    vec3 lightDir = normalize(lightPos - FragPos);

    float diff = max(dot(norm, lightDir), 0.0);

    vec3 diffuse = diff * lightColor;

    

    // specular

    float specularStrength = 0.5;

    vec3 viewDir = normalize(viewPos - FragPos);

    vec3 reflectDir = reflect(-lightDir, norm);  

    float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32);

    vec3 specular = specularStrength * spec * lightColor;  

        

    vec3 result = (ambient + diffuse + specular) * objectColor;

    FragColor = vec4(result, 1.0);

}

```

6. 帧缓冲的使用 (用于后处理效果)

```cpp

unsigned int framebuffer;

glGenFramebuffers(1, &framebuffer);

glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);

// 创建颜色附件纹理

unsigned int textureColorbuffer;

glGenTextures(1, &textureColorbuffer);

glBindTexture(GL_TEXTURE_2D, textureColorbuffer);

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, SCR_WIDTH, SCR_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureColorbuffer, 0);

// 创建渲染缓冲对象

unsigned int rbo;

glGenRenderbuffers(1, &rbo);

glBindRenderbuffer(GL_RENDERBUFFER, rbo);

glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, SCR_WIDTH, SCR_HEIGHT);

glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo);

// 检查帧缓冲是否完整

if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)

    std::cout << "ERROR::FRAMEBUFFER:: Framebuffer is not complete!" << std::endl;

glBindFramebuffer(GL_FRAMEBUFFER, 0);

// 使用帧缓冲

glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);

// 渲染场景...

glBindFramebuffer(GL_FRAMEBUFFER, 0);

// 使用后处理着色器渲染屏幕四边形...

```

高级举例

1. 延迟渲染 (Deferred Rendering)

延迟渲染是一种高级渲染技术,它将光照计算延迟到屏幕空间中进行,可以有效处理大量光源的场景。

几何通道顶点着色器:

```glsl

#version 330 core

layout (location = 0) in vec3 aPos;

layout (location = 1) in vec3 aNormal;

layout (location = 2) in vec2 aTexCoords;

out vec3 FragPos;

out vec3 Normal;

out vec2 TexCoords;

uniform mat4 model;

uniform mat4 view;

uniform mat4 projection;

void main()

{

    FragPos = vec3(model * vec4(aPos, 1.0));

    Normal = mat3(transpose(inverse(model))) * aNormal;  

    TexCoords = aTexCoords;

    

    gl_Position = projection * view * vec4(FragPos, 1.0);

}

```

几何通道片段着色器:

```glsl

#version 330 core

layout (location = 0) out vec3 gPosition;

layout (location = 1) out vec3 gNormal;

layout (location = 2) out vec4 gAlbedoSpec;

in vec3 FragPos;

in vec3 Normal;

in vec2 TexCoords;

uniform sampler2D texture_diffuse1;

uniform sampler2D texture_specular1;

void main()

{    

    gPosition = FragPos;

    gNormal = normalize(Normal);

    gAlbedoSpec.rgb = texture(texture_diffuse1, TexCoords).rgb;

    gAlbedoSpec.a = texture(texture_specular1, TexCoords).r;

}

```

光照通道片段着色器:

```glsl

#version 330 core

out vec4 FragColor;

in vec2 TexCoords;

uniform sampler2D gPosition;

uniform sampler2D gNormal;

uniform sampler2D gAlbedoSpec;

struct Light {

    vec3 Position;

    vec3 Color;

    float Linear;

    float Quadratic;

};

const int NR_LIGHTS = 32;

uniform Light lights[NR_LIGHTS];

uniform vec3 viewPos;

void main()

{             

    vec3 FragPos = texture(gPosition, TexCoords).rgb;

    vec3 Normal = texture(gNormal, TexCoords).rgb;

    vec3 Diffuse = texture(gAlbedoSpec, TexCoords).rgb;

    float Specular = texture(gAlbedoSpec, TexCoords).a;

    

    vec3 lighting = Diffuse * 0.1; // 环境光

    vec3 viewDir = normalize(viewPos - FragPos);

    for(int i = 0; i < NR_LIGHTS; ++i)

    {

        // 漫反射

        vec3 lightDir = normalize(lights[i].Position - FragPos);

        vec3 diffuse = max(dot(Normal, lightDir), 0.0) * Diffuse * lights[i].Color;

        // 镜面反射

        vec3 halfwayDir = normalize(lightDir + viewDir);  

        float spec = pow(max(dot(Normal, halfwayDir), 0.0), 16.0);

        vec3 specular = lights[i].Color * spec * Specular;

        // 衰减

        float distance = length(lights[i].Position - FragPos);

        float attenuation = 1.0 / (1.0 + lights[i].Linear * distance + lights[i].Quadratic * distance * distance);

        diffuse *= attenuation;

        specular *= attenuation;

        lighting += diffuse + specular;

    }

    FragColor = vec4(lighting, 1.0);

}

```

2. 几何着色器 (Geometry Shader) 示例

这个例子展示了如何使用几何着色器生成法线可视化:

顶点着色器:

```glsl

#version 330 core

layout (location = 0) in vec3 aPos;

layout (location = 1) in vec3 aNormal;

out VS_OUT {

    vec3 normal;

} vs_out;

uniform mat4 projection;

uniform mat4 view;

uniform mat4 model;

void main()

{

    gl_Position = projection * view * model * vec4(aPos, 1.0);

    mat3 normalMatrix = mat3(transpose(inverse(view * model)));

    vs_out.normal = normalize(vec3(projection * vec4(normalMatrix * aNormal, 0.0)));

}

```

几何着色器:

```glsl

#version 330 core

layout (triangles) in;

layout (line_strip, max_vertices = 6) out;

in VS_OUT {

    vec3 normal;

} gs_in[];

const float MAGNITUDE = 0.2;

void GenerateLine(int index)

{

    gl_Position = gl_in[index].gl_Position;

    EmitVertex();

    gl_Position = gl_in[index].gl_Position + vec4(gs_in[index].normal, 0.0) * MAGNITUDE;

    EmitVertex();

    EndPrimitive();

}

void main()

{

    GenerateLine(0); // 第一个顶点法线

    GenerateLine(1); // 第二个顶点法线

    GenerateLine(2); // 第三个顶点法线

}

```

3. 实例化渲染 (Instanced Rendering)

这个技术可以高效地渲染大量相似的对象:

顶点着色器:

```glsl

#version 330 core

layout (location = 0) in vec3 aPos;

layout (location = 1) in vec3 aNormal;

layout (location = 2) in vec2 aTexCoords;

layout (location = 3) in mat4 instanceMatrix;

out vec2 TexCoords;

out vec3 FragPos;

out vec3 Normal;

uniform mat4 projection;

uniform mat4 view;

void main()

{

    FragPos = vec3(instanceMatrix * vec4(aPos, 1.0));

    Normal = mat3(transpose(inverse(instanceMatrix))) * aNormal;  

    TexCoords = aTexCoords;

    

    gl_Position = projection * view * instanceMatrix * vec4(aPos, 1.0);

}

```

C++代码:

```cpp

// 生成大量的模型矩阵

unsigned int amount = 100000;

glm::mat4* modelMatrices;

modelMatrices = new glm::mat4[amount];

srand(glfwGetTime()); // 初始化随机种子

float radius = 50.0;

float offset = 2.5f;

for(unsigned int i = 0; i < amount; i++)

{

    glm::mat4 model = glm::mat4(1.0f);

    // 1. 位移:分布在半径为 'radius' 的圆形上,偏移的范围是 [-offset, offset]

    float angle = (float)i / (float)amount * 360.0f;

    float displacement = (rand() % (int)(2 * offset * 100)) / 100.0f - offset;

    float x = sin(angle) * radius + displacement;

    displacement = (rand() % (int)(2 * offset * 100)) / 100.0f - offset;

    float y = displacement * 0.4f; // 让行星带的高度比x和z的宽度要小

    displacement = (rand() % (int)(2 * offset * 100)) / 100.0f - offset;

    float z = cos(angle) * radius + displacement;

    model = glm::translate(model, glm::vec3(x, y, z));

    // 2. 缩放:在 0.05 和 0.25f 之间缩放

    float scale = (rand() % 20) / 100.0f + 0.05;

    model = glm::scale(model, glm::vec3(scale));

    // 3. 旋转:绕着一个(半)随机选择的旋转轴向量进行随机的旋转

    float rotAngle = (rand() % 360);

    model = glm::rotate(model, rotAngle, glm::vec3(0.4f, 0.6f, 0.8f));

    // 4. 添加到矩阵的数组中

    modelMatrices[i] = model;

}

// 配置实例化数组

unsigned int buffer;

glGenBuffers(1, &buffer);

glBindBuffer(GL_ARRAY_BUFFER, buffer);

glBufferData(GL_ARRAY_BUFFER, amount * sizeof(glm::mat4), &modelMatrices[0], GL_STATIC_DRAW);

// 设置实例化顶点属性(每个mat4占用4个顶点属性)

for(unsigned int i = 0; i < 4; i++)

{

    glEnableVertexAttribArray(3 + i);

    glVertexAttribPointer(3 + i, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (void*)(sizeof(glm::vec4) * i));

    glVertexAttribDivisor(3 + i, 1);

}

// 渲染

glDrawArraysInstanced(GL_TRIANGLES, 0, 36, amount);

```

4. 点光源阴影

这个例子展示了如何实现点光源的阴影映射:

深度着色器 (几何着色器):

```glsl

#version 330 core

layout (triangles) in;

layout (triangle_strip, max_vertices=18) out;

uniform mat4 shadowMatrices[6];

out vec4 FragPos; // FragPos from GS (output per emitvertex)

void main()

{

    for(int face = 0; face < 6; ++face)

    {

        gl_Layer = face; // built-in variable that specifies to which face we render.

        for(int i = 0; i < 3; ++i) // for each triangle's vertices

        {

            FragPos = gl_in[i].gl_Position;

            gl_Position = shadowMatrices[face] * FragPos;

            EmitVertex();

        }    

        EndPrimitive();

    }

}

```

阴影计算片段着色器:

```glsl

#version 330 core

out vec4 FragColor;

in VS_OUT {

    vec3 FragPos;

    vec3 Normal;

    vec2 TexCoords;

} fs_in;

uniform sampler2D diffuseTexture;

uniform samplerCube depthMap;

uniform vec3 lightPos;

uniform vec3 viewPos;

uniform float far_plane;

float ShadowCalculation(vec3 fragPos)

{

    vec3 fragToLight = fragPos - lightPos;

    float closestDepth = texture(depthMap, fragToLight).r;

    closestDepth *= far_plane;

    float currentDepth = length(fragToLight);

    float bias = 0.05;

    float shadow = currentDepth -  bias > closestDepth ? 1.0 : 0.0;

    return shadow;

}

void main()

{           

    vec3 color = texture(diffuseTexture, fs_in.TexCoords).rgb;

    vec3 normal = normalize(fs_in.Normal);

    vec3 lightColor = vec3(0.3);

    // Ambient

    vec3 ambient = 0.3 * color;

    // Diffuse

    vec3 lightDir = normalize(lightPos - fs_in.FragPos);

    float diff = max(dot(lightDir, normal), 0.0);

    vec3 diffuse = diff * lightColor;

    // Specular

    vec3 viewDir = normalize(viewPos - fs_in.FragPos);

    vec3 reflectDir = reflect(-lightDir, normal);

    float spec = 0.0;

    vec3 halfwayDir = normalize(lightDir + viewDir);  

    spec = pow(max(dot(normal, halfwayDir), 0.0), 64.0);

    vec3 specular = spec * lightColor;    

    // 计算阴影

    float shadow = ShadowCalculation(fs_in.FragPos);                      

    vec3 lighting = (ambient + (1.0 - shadow) * (diffuse + specular)) * color;    

    

    FragColor = vec4(lighting, 1.0);

}

```

这些高级例子展示了OpenGL的一些更复杂的特性和技术。它们需要更深入的理解和更多的设置,但可以实现更高级的视觉效果和更好的性能。在实际应用中,你可能需要根据具体需求来调整和优化这些技术。

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值