Простой SSAO с Three.jsHtml

Программисты Html
Ответить
Anonymous
 Простой SSAO с Three.js

Сообщение Anonymous »

Я хочу создать SSAO с помощью Three.js и шейдеров, я использовал customLambertMaterial и пользовательские шейдеры
теперь я хочу реализовать функцию SSAO без композитора
инициализировать мой ssaoRender

Код: Выделить всё

RenderView.ssaoRenderer = new SSAORenderer(this._renderer as THREE.WebGLRenderer, this._renderEngine.mainScene, camera );
следующий в функции рендеринга

Код: Выделить всё

if (RenderView.ssaoRenderer?.enabled) {
RenderView.ssaoRenderer.render();
} else {
renderer.render(this, camera);
}
Мой шейдер

Код: Выделить всё

export const ssaoVertexShader = `
varying vec2 vUv;

void main() {
vUv = uv;
gl_Position = vec4(position.xy, 0.0, 1.0);
}
`;

export const ssaoFragmentShader = `
varying vec2 vUv;

uniform sampler2D depthMap;
uniform sampler2D rotateMap;
uniform float zNear;
uniform float zFar;
uniform float radius;
uniform float attBias;
uniform float attScale;

vec3 rndTable[8];

void initRndTable() {
rndTable[0] = vec3(-0.5, -0.5, -0.5);
rndTable[1] = vec3(0.5, -0.5, -0.5);
rndTable[2] = vec3(-0.5, 0.5, -0.5);
rndTable[3] = vec3(0.5, 0.5, -0.5);
rndTable[4] = vec3(-0.5, -0.5, 0.5);
rndTable[5] = vec3(0.5, -0.5, 0.5);
rndTable[6] = vec3(-0.5, 0.5, 0.5);
rndTable[7] = vec3(0.5, 0.5, 0.5);
}

float linearizeDepth(float z) {
float ndc = z * 2.0 - 1.0;
return 2.0 * zNear * zFar / (zFar + zNear - ndc * (zFar - zNear));
}

void main() {
initRndTable();

float zb = texture2D(depthMap, vUv).r;
float z = linearizeDepth(zb);

vec3 plane = 2.0 * texture2D(rotateMap, vUv).xyz - 1.0;
float att = 0.0;

for (int i = 0; i < 8; i++) {
vec3 sampleVec = reflect(rndTable[i], plane);
vec2 offsetUv = vUv + radius * sampleVec.xy / z;
if (offsetUv.x < 0.0 || offsetUv.x > 1.0 || offsetUv.y < 0.0 || offsetUv.y > 1.0) continue;

float zSample = texture2D(depthMap, offsetUv).r;
zSample = linearizeDepth(zSample);

if (zSample - z >  0.1) continue;

float dz = max(zSample - z, 0.0) * 30.0;
att += 1.0 / (1.0 + dz * dz);
}

att = clamp((att / 8.0 + attBias) * attScale, 0.0, 1.0);
gl_FragColor = vec4(vec3(att), 1.0);
}

`;
ssaoRender

Код: Выделить всё

    ssaoRenderer.ts
import { THREE } from '@render/three';
import { DepthPass } from './depthPass';
import { ssaoFragmentShader, ssaoVertexShader } from '@render/utils/ssaoPass';

export class SSAORenderer {

private renderer: THREE.WebGLRenderer;
private scene: THREE.Scene;
private camera: THREE.Camera;

private depthPass: DepthPass;
private ssaoMaterial: THREE.ShaderMaterial;

private quadScene: THREE.Scene;
private quadCamera: THREE.OrthographicCamera;

enabled = true;

constructor(renderer: THREE.WebGLRenderer, scene: THREE.Scene, camera: THREE.Camera){
this.renderer = renderer;
this.scene = scene;
this.camera = camera;

const width = renderer.domElement.width;
const height = renderer.domElement.height;

this.depthPass = new DepthPass(width, height);

this.ssaoMaterial = new THREE.ShaderMaterial({
vertexShader: ssaoVertexShader,
fragmentShader: ssaoFragmentShader,
uniforms: {
depthMap: { value: null },
rotateMap: { value: null },
zNear: { value: (camera as THREE.PerspectiveCamera).near },
zFar: { value: (camera as THREE.PerspectiveCamera).far },
radius: { value: 0.2 },
attBias: { value: 0.3 },
attScale: { value: 1.0 }
}
});

const quad = new THREE.Mesh(new THREE.PlaneGeometry(2,2), this.ssaoMaterial);

this.quadScene = new THREE.Scene();
this.quadScene.add(quad);

this.quadCamera = new THREE.OrthographicCamera(-1,1,1,-1,0,1);

this.ssaoMaterial.uniforms.projectionMatrix = { value: camera.projectionMatrix };
this.ssaoMaterial.uniforms.invProjectionMatrix = { value: camera.projectionMatrixInverse };
}

public render(){
if(!this.enabled){
this.renderer.render(this.scene, this.camera);
return;
}

this.ssaoMaterial.uniforms.projectionMatrix.value = this.camera.projectionMatrix;
this.ssaoMaterial.uniforms.invProjectionMatrix.value = this.camera.projectionMatrixInverse;

const width = this.renderer.domElement.width;
const height = this.renderer.domElement.height;

this.depthPass.render(this.renderer, this.scene, this.camera);

this.ssaoMaterial.uniforms.tDepth.value = this.depthPass.getDepthTexture();
this.ssaoMaterial.uniforms.tColor.value = this.depthPass.getColorTexture();
this.ssaoMaterial.uniforms.tNormal.value = this.depthPass.getNormalTexture();
this.ssaoMaterial.uniforms.resolution.value.set(width,height);

this.ssaoMaterial.uniforms.projectionMatrix.value = this.camera.projectionMatrix;
this.ssaoMaterial.uniforms.invProjectionMatrix.value = this.camera.projectionMatrixInverse;

this.renderer.render(this.quadScene, this.quadCamera);
}

public resize(width:number, height:number){
this.depthPass.resize(width,height);
this.ssaoMaterial.uniforms.resolution.value.set(width,height);
}

public setIntensity(v:number){
this.ssaoMaterial.uniforms.intensity.value = v;
}

public setRadius(v:number){
this.ssaoMaterial.uniforms.radius.value = v;
}
}
DeepPass

Код: Выделить всё

    // depthPass.ts
import { THREE } from '@render/three';

export class DepthPass {
public renderTarget: THREE.WebGLRenderTarget;
public normalTarget: THREE.WebGLRenderTarget;

private normalMaterial: THREE.ShaderMaterial;

constructor(width: number, height: number) {

this.renderTarget = new THREE.WebGLRenderTarget(width, height, {
minFilter:  THREE.NearestFilter,
magFilter: THREE.NearestFilter,
format: THREE.RGBAFormat
});
this.renderTarget.depthTexture = new THREE.DepthTexture(width, height);
this.renderTarget.depthTexture.format = THREE.DepthFormat;
this.renderTarget.depthTexture.type = THREE.FloatType;

this.renderTarget.depthBuffer = true;

this.normalTarget = new THREE.WebGLRenderTarget(width, height, {
minFilter: THREE.NearestFilter,
magFilter: THREE.NearestFilter,
format: THREE.RGBAFormat
});

this.normalMaterial = new THREE.ShaderMaterial({
vertexShader: `
varying vec3 vNormalView;
void main() {
vNormalView = normalize((viewMatrix * vec4(normal,0.0)).xyz);
gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
}
`,
fragmentShader: `
varying vec3 vNormalView;
void main() {
gl_FragColor = vec4(vNormalView * 0.5 + 0.5, 1.0);
}
`
});

}

public render2(renderer: THREE.WebGLRenderer, scene: THREE.Scene, camera: THREE.Camera) {

// depth only
const depthMaterial = new THREE.MeshDepthMaterial();
scene.overrideMaterial = depthMaterial;

renderer.setRenderTarget(this.renderTarget);
renderer.clear();
renderer.render(scene, camera);

scene.overrideMaterial = null;

renderer.setRenderTarget(null);
}

public render(renderer: THREE.WebGLRenderer, scene: THREE.Scene, camera: THREE.Camera) {
const originalMaterials = new Map();

scene.traverse(obj => {
if (obj instanceof THREE.Mesh && obj.material) {
originalMaterials.set(obj, obj.material);
}
});

renderer.setRenderTarget(this.renderTarget);
renderer.clear(true, true, true);
renderer.render(scene, camera);

scene.traverse(obj => {
if (obj instanceof THREE.Mesh) obj.material = this.normalMaterial;
});
renderer.setRenderTarget(this.normalTarget);
renderer.clear(true, true, true);
renderer.render(scene, camera);

scene.traverse(obj => {
if (obj instanceof THREE.Mesh && originalMaterials.has(obj)) {
obj.material = originalMaterials.get(obj)!;
}
});

renderer.setRenderTarget(null);
}

public resize(width: number, height: number) {
this.renderTarget.setSize(width, height);
this.normalTarget.setSize(width, height);
}

public getDepthTexture(): THREE.DepthTexture {
return this.renderTarget.depthTexture;
}

public getColorTexture(): THREE.Texture {
return this.renderTarget.texture;
}

public getNormalTexture(): THREE.Texture {
return this.normalTarget.texture;
}
}

Проблема:
Шейдер применен неправильно; он слегка затемняет всю модель, и нет эффекта SSAO.

Я активирую ssao с помощью флажка, активация вока - это хорошо

Подробнее здесь: https://stackoverflow.com/questions/798 ... h-three-js
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Html»