从零开始编写minecraft光影包(8)中级水面绘制 水下阴影与焦散

本文详细介绍了如何从零开始编写minecraft光影包,着重讲解了中级水面特效的实现,包括水下阴影绘制、基于深度的淡出、焦散效果的添加,以及修复染色玻璃透视问题。通过代码迁移和优化,实现了更加逼真的水面和水下视觉效果。
摘要由CSDN通过智能技术生成

完整资源:

我的Github地址

前情提要:

从0开始编写minecraft光影包(0)GLSL,坐标系,光影包结构介绍

从零开始编写minecraft光影包(1)基础阴影绘制

从零开始编写minecraft光影包(2)阴影优化

从零开始编写minecraft光影包(3)基础泛光绘制

从零开始编写minecraft光影包(4)泛光性能与品质优化

从零开始编写minecraft光影包(5)简单光照系统,曝光调节,色调映射与饱和度

从零开始编写minecraft光影包(6)天空绘制

从零开始编写minecraft光影包(7)基础水面绘制

前言

回到学习就不能摸鱼了🐎?还是来更新罢。。。

这次更新一些比较高级的水面特效的绘制,比如焦散,屏幕空间反射等等。。。

代码迁移

上一篇博客我们将水面绘制的代码写在了 gbuffers_water 着色器中,但是这么做有几个不好的地方:

  1. 需要重复计算天空颜色
  2. 在后续绘制天空漫反射的时候,因为天空是在 composite 着色器中绘制的,所以绘制针对天空的漫反射将会变得十分困难
  3. 在后续的编程中我们将绘制屏幕空间反射,这一步需要将反射的颜色和基色混合,同样因为水面的绘制在 gbuffers_water 着色器,这使得最后颜色的混合变得十分困难

好吧就是我当时写的时候没有考虑清楚,我菜,我爬爬爬 dbq 呜呜呜

话不多🔒开始动工,我们将水面的基础绘制,迁移到 composite 着色器中进行:

首先将 gbuffers_water 着色器改写。我们首先修改 gbuffers_water.vsh,我们不再计算天空颜色,而是只计算法线,并且计算水面凹凸,施加到顶点上:

#version 120

attribute vec2 mc_Entity;

uniform mat4 gbufferProjection;
uniform mat4 gbufferProjectionInverse;
uniform mat4 gbufferModelView;
uniform mat4 gbufferModelViewInverse;

uniform vec3 cameraPosition;

uniform int worldTime;

varying float id;

varying vec3 normal;

varying vec4 texcoord;
varying vec4 lightMapCoord;
varying vec4 color;

/*
 *  @function getBump          : 水面凹凸计算
 *  @param positionInViewCoord : 眼坐标系中的坐标
 *  @return                    : 计算凹凸之后的眼坐标
 */
vec4 getBump(vec4 positionInViewCoord) {
    vec4 positionInWorldCoord = gbufferModelViewInverse * positionInViewCoord;  // “我的世界坐标”
    positionInWorldCoord.xyz += cameraPosition; // 世界坐标(绝对坐标)

    // 计算凹凸
    positionInWorldCoord.y += sin(float(worldTime*0.3) + positionInWorldCoord.z * 2) * 0.05;

    positionInWorldCoord.xyz -= cameraPosition; // 转回 “我的世界坐标”
    return gbufferModelView * positionInWorldCoord; // 返回眼坐标
}

void main() {
    vec4 positionInViewCoord = gl_ModelViewMatrix * gl_Vertex;   // mv变换计算眼坐
    if(mc_Entity.x == 10091) {  // 如果是水则计算凹凸
        gl_Position = gbufferProjection * getBump(positionInViewCoord);  // p变换
    } else {    // 否则直接传递坐标
        gl_Position = gbufferProjection * positionInViewCoord;  // p变换
    }

    color = gl_Color;   // 基色
    id = mc_Entity.x;   // 方块id
    normal = gl_NormalMatrix * gl_Normal;   // 眼坐标系中的法线
    lightMapCoord = gl_TextureMatrix[1] * gl_MultiTexCoord1;    // 光照纹理坐标
    texcoord = gl_TextureMatrix[0] * gl_MultiTexCoord0; // 纹理坐标
}

然后在 gbuffers_water.fsh 中,我们也不计算水面的颜色,取而代之我们直接输出一个颜色即可。值得注意的是我们将眼坐标下的法线方向传递到四号缓冲区

#version 120

uniform sampler2D texture;
uniform sampler2D lightmap;

uniform vec3 cameraPosition;

uniform int worldTime;

varying float id;

varying vec3 normal;    // 法向量在眼坐标系下

varying vec4 texcoord;
varying vec4 color;
varying vec4 lightMapCoord;

/* DRAWBUFFERS: 04 */
void main() {
    vec4 light = texture2D(lightmap, lightMapCoord.st); // 光照
    if(id!=10091) {
        gl_FragData[0] = color * texture2D(texture, texcoord.st) * light;   // 不是水面则正常绘制纹理
        gl_FragData[1] = vec4(normal*0.5+0.5, 0.5);   // 法线
    } else {    // 是水面则输出 vec3(0.05, 0.2, 0.3)
        gl_FragData[0] = vec4(vec3(0.05, 0.2, 0.3), 0.5) 
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值