-
-
Notifications
You must be signed in to change notification settings - Fork 384
Closed
Labels
glTFrenderingRendering related functionsRendering related functionsshaderShader related functionsShader related functions
Milestone
Description
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
- 基于屏幕空间,通过 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 );
}
- 其中 transmissionSamplerMap 来源:
uniforms.transmission.value = material.transmission;
uniforms.transmissionSamplerMap.value = transmissionRenderTarget.texture;
uniforms.transmissionSamplerSize.value.set( transmissionRenderTarget.width, transmissionRenderTarget.height );
- transmissionRenderTarget来自于renderTransmissionPass,这个pass处理了opaque object和transmissive object:
https://github.com/mrdoob/three.js/blob/3f2956c35e1bd1fc8cbe35f1430e475fd848e6a2/src/renderers/WebGLRenderer.js#L1444 - 并且three.js直接将 transmission 和 volume 的厚度算法放到一起,直接通过 USE_TRANSMISSION 这个宏去控制整体
https://github.com/mrdoob/three.js/blob/3f2956c35e1bd1fc8cbe35f1430e475fd848e6a2/src/renderers/shaders/ShaderChunk/transmission_fragment.glsl.js#L1 - 最终折射颜色输出的时候three.js把可以模拟钻石效果的色散计算(USE_DISPERSION)也放到了折射算法部分
https://github.com/mrdoob/three.js/blob/3f2956c35e1bd1fc8cbe35f1430e475fd848e6a2/src/renderers/shaders/ShaderChunk/transmission_pars_fragment.glsl.js#L178
babylon
- 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);
}
}
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);
- refractionTexture继承自RenderTargetTexture:
htthttps://github.com/BabylonJS/Babylon.js/blob/e98b900a49b989f3215b002eeb65d0e23cf005b5/packages/dev/core/src/Materials/Textures/refractionTexture.ts#L9
filament
- filament 支持将 refractionMode 设置为 cubemap 或者 screenspace ,然后 refractionType 支持两种:solid、thin,solid 用于较厚的物体,thin 用于较薄的物体。
- 所有跟折射相关的宏都包在了 MATERIAL_HAS_REFRACTION 下:
(IOR、absorption(吸收系数)、Micro-thickness and thickness)
https://github.com/google/filament/blob/1c2ffc9ed4581080e53b23dda63ed7bfee6311e7/shaders/src/shading_lit.fs#L102
折射的具体算法放在了间接光部分:
包含了采样 cubemap 和 screenspace 两种算法
https://github.com/google/filament/blob/1c2ffc9ed4581080e53b23dda63ed7bfee6311e7/shaders/src/light_indirect.fs#L493
screenspace下的折射uv通过相应的矩阵转换取到:
- 所有跟折射相关的宏都包在了 MATERIAL_HAS_REFRACTION 下:
// 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能满足最基本效果
GuoLei1990
Metadata
Metadata
Assignees
Labels
glTFrenderingRendering related functionsRendering related functionsshaderShader related functionsShader related functions