Hi Omar, thanks so much for putting this out there!!! Wonderful work. I tried to reproduce it in my own project, but am getting this error on both firefox and Chrome. My browsers support webGL 1 and 2:
THREE.WebGLProgram: Shader Error 0 - VALIDATE_STATUS false
Program Info Log: Must have a compiled fragment shader attached:
SHADER_INFO_LOG:
ERROR: 0:145: '0.0' : syntax error
FRAGMENT
ERROR: 0:145: '0.0' : syntax error
[three.module.js:18957](webpack:///node_modules/three/build/three.module.js)
WebGLProgram three.module.js:18957
acquireProgram three.module.js:19656
getProgram three.module.js:27381
setProgram three.module.js:27586
renderBufferDirect three.module.js:26710
renderObject three.module.js:27318
renderObjects three.module.js:27287
renderScene three.module.js:27209
render three.module.js:27029
render Pass.js:62
render CustomOutlinePass.js:83
render EffectComposer.js:141
update Renderer.js:85
update Experience.js:68
Experience Experience.js:54
trigger EventEmitter.js:138
trigger EventEmitter.js:136
tick Time.js:28
Time Time.js:17
(Async: FrameRequestCallback)
Time Time.js:15
Experience Experience.js:36
<anonymous> script.js:5
<anonymous> bundle.eadd6e7c63194188.js:67059
<anonymous> bundle.eadd6e7c63194188.js:67061
It seems like the fragment shader can't be recognized? I simply copied the CustomOutlinePass.js.
Below is what my renderer code looks like. If I comment out the last line, this.composer.render();
and use the original renderer, the rendering works.
import * as THREE from 'three'
import Experience from './Experience.js'
import { EffectComposer } from "three/examples/jsm/postprocessing/EffectComposer.js";
import { RenderPass } from "three/examples/jsm/postprocessing/RenderPass.js";
import { ShaderPass } from "three/examples/jsm/postprocessing/ShaderPass.js";
import { FXAAShader } from "three/examples/jsm/shaders/FXAAShader.js";
import { CustomOutlinePass } from "./Utils/Shading/CustomOutlinePass.js";
export default class Renderer
{
constructor()
{
this.experience = new Experience()
this.canvas = this.experience.canvas
this.sizes = this.experience.sizes
this.scene = this.experience.scene
this.camera = this.experience.camera
this.setInstance()
}
setInstance()
{
this.instance = new THREE.WebGLRenderer({
canvas: this.canvas,
antialias: true
})
this.instance.physicallyCorrectLights = true
this.instance.outputEncoding = THREE.sRGBEncoding
this.instance.toneMapping = THREE.CineonToneMapping
this.instance.toneMappingExposure = 1.75
this.instance.shadowMap.enabled = true
this.instance.shadowMap.type = THREE.PCFSoftShadowMap
this.instance.setClearColor('#211d20')
this.instance.setSize(this.sizes.width, this.sizes.height)
this.instance.setPixelRatio(Math.min(this.sizes.pixelRatio, 2))
// Set up post processing
// Create a render target that holds a depthTexture so we can use it in the outline pass
// See: https://threejs.org/docs/index.html#api/en/renderers/WebGLRenderTarget.depthBuffer
const depthTexture = new THREE.DepthTexture();
this.renderTarget = new THREE.WebGLRenderTarget(
this.sizes.width,
this.sizes.height,
{
depthTexture: depthTexture,
depthBuffer: true,
}
);
// Initial render pass.
this.composer = new EffectComposer(this.instance, this.renderTarget);
const pass = new RenderPass(this.scene, this.camera.instance);
this.composer.addPass(pass);
// Outline pass.
this.customOutline = new CustomOutlinePass(
new THREE.Vector2(this.sizes.width, this.sizes.height),
this.scene,
this.camera.instance
);
this.composer.addPass(this.customOutline);
// Antialias pass.
this.effectFXAA = new ShaderPass(FXAAShader);
this.effectFXAA.uniforms["resolution"].value.set(
1 / this.sizes.width,
1 / this.sizes.height
);
this.composer.addPass(this.effectFXAA);
}
resize()
{
this.instance.setSize(this.sizes.width, this.sizes.height)
this.instance.setPixelRatio(Math.min(this.sizes.pixelRatio, 2))
// this.composer.setSize(window.innerWidth, window.innerHeight);
// this.effectFXAA.setSize(window.innerWidth, window.innerHeight);
// this.customOutline.setSize(window.innerWidth, window.innerHeight);
}
update()
{
// this.instance.render(this.scene, this.camera.instance)
this.composer.render();
}
}