Qt::QOpenGLWidget 渲染天空壳

在qt窗口中嵌入opengl渲染天空壳和各种立方体

一 学前知识

天空壳的渲染学前小知识

1 立方体贴图 天空壳的渲染就是利用立方体贴图来实现渲染流程

2 基础光照 光照模型

3 opengl帧缓冲 如何自定义帧缓冲实现后期特效

4 glsl常见的shader内置函数 glsl编程常用的内置函数

5 材质 材质的渲染原理

二 shader代码

1 顶点着色器

#version 410 core
//顶点着色器
uniform mat4 lightview;
uniform mat4 projection_mat;
uniform mat4 view_mat;
uniform mat4 model_mat;
uniform mat3 normal_mat;
uniform vec4 light_position;
uniform vec4 light_ambient;
uniform vec4 light_diffuse;
uniform vec4 light_specular;
uniform vec4 material_specular;
uniform float material_shininess;
uniform int  render_type;

layout(location = 0) in vec3 a_position;
layout(location = 1) in vec3 a_texcoord;
layout(location = 2) in vec3 a_normal;

layout(location = 0) out vec3 position;
layout(location = 1) out vec3 normal;
layout(location = 2) out vec3 texcoord;
layout(location = 3) out vec4 lightDirection;
layout(location = 4) out vec4 color;

void main()
{
    //给像素着色器传递参数
    {
        //光照方向
        lightDirection = lightview * light_position;
        //法线向量
        normal = normal_mat * a_normal;
        //纹理坐标
        texcoord = a_texcoord;
        //颜色
        color = vec4(1.0f, 1.0f, 1.0f, 0.0f);
        //观察空间坐标(从右向左做运算) = 观察矩阵 * 变换矩阵 * 局部空间坐标
        position = (view_mat * model_mat * vec4(a_position, 1)).xyz;
    }
    //如果是渲染立方体
    if (render_type == 0)
    {
        //最终屏幕坐标 = 透视矩阵 * 观察矩阵 * 变换矩阵 * 局部空间坐标(从右向左做运算)
        gl_Position = projection_mat *  view_mat * model_mat * vec4(a_position, 1);
    }
    else  //如果是渲染天空壳
    {
        /*
           天空盒很可能会渲染在所有其他对象之上,因为它只是一个1x1x1的立方体(意味着距离
        摄像机的距离也只有1),我们需要欺骗深度缓冲,让它认为天空盒有着最大的深度值1.0,只
        要它前面有一个物体,深度测试就会失败。
           在坐标系统小节中我们说过,透视除法是在顶点着色器运行之后执行的,将gl_Position的xyz
        坐标除以w分量。我们又从深度测试小节中知道,相除结果的z分量等于顶点的深度值。使用这些信
        息,我们可以将输出位置的z分量等于它的w分量,让z分量永远等于1.0,这样子的话,当透视
        除法执行之后,z分量会变为w / w = 1.0。
        */
        vec4 pos = projection_mat *  view_mat * model_mat * vec4(a_position, 1);
        gl_Position = pos.xyww;
    }
}

2 天空壳像素着色器

#version 410 core
//像素着色器
#extension GL_NV_shadow_samplers_cube : enable
out vec4 FragColor;

layout(location = 0) in vec3 position;
layout(location = 1) in vec3 normal;
layout(location = 2) in vec3 texcoord;
layout(location = 3) in vec4 lightDirection;

uniform samplerCube env;
uniform vec4 light_position;
uniform vec4 light_ambient;
uniform vec4 light_diffuse;
uniform vec4 light_specular;
uniform vec4 material_specular;
uniform float material_shininess;

void main() 
{ 
    //输出颜色 = 直接取天空壳纹理色
    FragColor = textureCube(env,texcoord.xyz);
}

3 中心立方体像素着色器

#version 410 core
//像素着色器
#extension GL_NV_shadow_samplers_cube : enable
out vec4 FragColor;

layout(location = 0) in vec3 position;
layout(location = 1) in vec3 normal;
layout(location = 2) in vec3 texcoord;
layout(location = 3) in vec4 lightDirection;
layout(location = 4) in vec4 color;

uniform sampler2D tex;
uniform vec4 basicColor;
uniform vec4 light_position;
uniform vec4 light_ambient;
uniform vec4 light_diffuse;
uniform vec4 light_specular;
uniform vec4 material_specular;
uniform float material_shininess;

void main()
{
    //归一化法线向量
    vec3 N = normalize(normal);

    //光照和法向量的夹角的cos值
    float NdotL = dot(N, lightDirection.xyz);
    //反射光照和法向量的夹角的cos值
    float RdotL = dot(reflect(normalize(position), N), lightDirection.xyz);

    //向量的绝对值
    vec3 absN = abs(texcoord.xyz);
    //把立方体坐标系移到坐标轴的原点
    vec3 zerttexcoord = texcoord + 0.5;
    vec2 texCoord;
    //左右两个面(纹理取向量yz)
    if (absN.x > absN.y && absN.x > absN.z)
        texCoord = vec2(zerttexcoord.yz);
    //上下两个面
    else if (absN.y > absN.z)
        texCoord = vec2(zerttexcoord.zx);
    //前后两个面
    else
        texCoord = vec2(zerttexcoord.xy);

    //获取对应坐标纹理的颜色值
    vec4 texColor = texture(tex, texCoord.xy);
    //混合基础颜色和纹理色
    vec4 unlitColor = color * mix(basicColor, vec4(texColor.xyz, 1.0), texColor.w);
    //输出最终颜色 =(环境光照 + 漫反射光照 * 光照夹角cos值) * 初始颜色 + 材质的颜色
    FragColor = (light_ambient + light_diffuse * max(NdotL, 0.0)) * unlitColor +
                    material_specular * light_specular * pow(max(RdotL, 0.0), material_shininess);
}

4 更完整的项目地址:

gitee地址

github 地址

三 运行效果展示

四 参考文章

1 噪声算法

2 不只是噪音

3 Normal Matrix(法向量变换矩阵)

4 深度好文:关于图形渲染以及离屏渲染

5 OpenGL-离屏渲染

6 OpenGL Frame Buffer Object (FBO)

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值