Thanks to visit codestin.com
Credit goes to github.com

Skip to content

volume #2351

@hhhhkrx

Description

@hhhhkrx

GLTF

https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_materials_volume
https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_materials_transmission
根据gltf官方给出的参考,volume的算法需要和KHR_materials_transmission相结合,transmission只模拟了光的透射,volume增加了厚度的算法,折射率的输入则是需要和KHR_materials_ior结合,最终暴露给用户的uniform:

"materials": [
    {
        "extensions": {
            "KHR_materials_volume": {
                "thicknessFactor": 1.0,
                "attenuationDistance":  0.006,
                "attenuationColor": [ 0.5, 0.5, 0.5 ]
            }
        }
    }
]

KHR_materials_transmission参考:

materials: [
  {
    "extensions": {
       "KHR_materials_transmission": {
         "transmissionFactor": 0.8,
         "transmissionTexture": {
           "index": 0
         }
       }
    }
  }
]

three.js

image

  • 基于屏幕空间,通过 getTransmissionSample 函数采样屏幕上的 framebuffer
vec4 getTransmissionSample( const in vec2 fragCoord, const in float roughness, const in float ior ) {

		float lod = log2( transmissionSamplerSize.x ) * applyIorToRoughness( roughness, ior );
		return textureBicubic( transmissionSamplerMap, fragCoord.xy, lod );

	}

https://github.com/mrdoob/three.js/blob/e6f98724943459ea395c856a253200e8aac61ceb/src/renderers/shaders/ShaderChunk/transmission_pars_fragment.glsl.js#L170

  • 其中 transmissionSamplerMap 来源:
uniforms.transmission.value = material.transmission;
uniforms.transmissionSamplerMap.value = transmissionRenderTarget.texture;
uniforms.transmissionSamplerSize.value.set( transmissionRenderTarget.width, transmissionRenderTarget.height );

babylon

image

https://github.com/BabylonJS/Babylon.js/blob/1e2bc74ead52b91030a6abd9695e5a5f175b0758/packages/dev/core/src/Shaders/ShadersInclude/pbrBlockSubSurface.fx#L36

  • 2d refractionSampler 采样基于屏幕空间:
#ifdef SS_REFRACTIONMAP_3D
                , in samplerCube refractionSampler
                #ifndef LODBASEDMICROSFURACE
                    , in samplerCube refractionSamplerLow
                    , in samplerCube refractionSamplerHigh
                #endif
            #else
                , in sampler2D refractionSampler
                #ifndef LODBASEDMICROSFURACE
                    , in sampler2D refractionSamplerLow
                    , in sampler2D refractionSamplerHigh
                #endif
            #endif
  if (this._refractionTexture && StandardMaterial.RefractionTextureEnabled) {
                    if (this._refractionTexture.isCube) {
                        effect.setTexture("refractionCubeSampler", this._refractionTexture);
                    } else {
                        effect.setTexture("refraction2DSampler", this._refractionTexture);
                    }
                }

折射坐标
https://github.com/BabylonJS/Babylon.js/blob/ba1b14818cbcfbc244b96ca2b127544fd19b5c15/packages/dev/core/src/ShadersWGSL/default.fragment.fx#L224

vec3 vRefractionUVW = vec3(refractionMatrix * (view * vec4(vPositionW + refractionVector * vRefractionInfos.z, 1.0)));

		vec2 refractionCoords = vRefractionUVW.xy / vRefractionUVW.z;

		refractionCoords.y = 1.0 - refractionCoords.y;

		refractionColor = texture2D(refraction2DSampler, refractionCoords);

filament

image
image

    // compute the point where the ray exits the medium, if needed
    vec4 p = vec4(getClipFromWorldMatrix() * vec4(ray.position, 1.0));
    p.xy = uvToRenderTargetUV(p.xy * (0.5 / p.w) + 0.5);

UNITY HDRP

https://docs.unity3d.com/Packages/[email protected]/manual/Refraction-in-HDRP.html
unity的内置折射是基于HDRP管线,并且采用屏幕空间计算,需要反射探针配合。

总结

● 优先实现屏幕空间效果,等后续探针功能接入,再考虑cubemap
● 如果按照屏幕空间算法的话,直接调用opaque texture能满足最基本效果

Metadata

Metadata

Assignees

Labels

glTFrenderingRendering related functionsshaderShader related functions

Type

No type

Projects

Status

Done

Status

Done

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions