Problem with gpgpu / water example

Hey,

when trying to run the above example, I receive this error within the initWater() function ‘Property ‘color’ does not exist on type ‘ShaderMaterial’.’

I’m writing this in typescript and converting to js through npm.

function initWater() {

var materialColor = 0x0040C0;

var geometry = new THREE.PlaneBufferGeometry( BOUNDS, BOUNDS, WIDTH - 1, WIDTH - 1 );

// material: make a THREE.ShaderMaterial clone of THREE.MeshPhongMaterial, with customized vertex shader
const material = new THREE.ShaderMaterial( {
    uniforms: THREE.UniformsUtils.merge( [
        THREE.ShaderLib[ 'phong' ].uniforms,
        {
            "heightmap": { value: null }
        }
    ] ),
    vertexShader: document.getElementById( 'waterVertexShader' ).textContent,
    fragmentShader: THREE.ShaderChunk[ 'meshphong_frag' ]

} );

material.lights = true;

// Material attributes from THREE.MeshPhongMaterial
material.color = new THREE.Color( materialColor );
material.specular = new THREE.Color( 0x111111 );
material.shininess = 50;

// Sets the uniforms with the material values
material.uniforms[ "diffuse" ].value = material.color;
material.uniforms[ "specular" ].value = material.specular;
material.uniforms[ "shininess" ].value = Math.max( material.shininess, 1e-4 );
material.uniforms[ "opacity" ].value = material.opacity;

// Defines
material.defines.WIDTH = WIDTH.toFixed( 1 );
material.defines.BOUNDS = BOUNDS.toFixed( 1 );

Thanks

color, specular and shininess are not properties of the THREE.ShaderMaterial
you need to set the uniforms directly.

Try changing your function to this.

function initWater() {
    var materialColor = 0x0040C0;
    var geometry = new THREE.PlaneBufferGeometry( BOUNDS, BOUNDS, WIDTH - 1, WIDTH - 1 );
    // material: make a THREE.ShaderMaterial clone of THREE.MeshPhongMaterial, with customized vertex shader
    const material: THREE.ShaderMaterial = new THREE.ShaderMaterial({
        uniforms: THREE.UniformsUtils.merge([
            THREE.ShaderLib['phong'].uniforms,
            {
                "heightmap": { value: null }
            }
        ]),
        vertexShader: document.getElementById('waterVertexShader').textContent,
        fragmentShader: THREE.ShaderChunk['meshphong_frag']
    });
    material.lights = true;
    // Material attributes from THREE.MeshPhongMaterial
    // material.color = new THREE.Color( materialColor );
    // material.specular = new THREE.Color( 0x111111 );
    // material.shininess = 50;
    // Sets the uniforms with the material values
    material.uniforms["diffuse"].value.setHex(materialColor);
    material.uniforms["specular"].value.setHex(0x111111);
    material.uniforms["shininess"].value = 50;
    material.uniforms["opacity"].value = material.opacity;
    // Defines
    material.defines.WIDTH = WIDTH.toFixed(1);
    material.defines.BOUNDS = BOUNDS.toFixed(1);
}
1 Like

Thanks Sean,

That seems to have cleared that problem up, although it still doesn’t seem to be working. I’m receiving these errors within my console.

Uncaught TypeError: Cannot read property ‘add’ of undefined
at initWater (client.js:151)
at init (client.js:90)
at client.js:31

I’ve created a JSFiddle file with the code, it would be great if you could take a look. https://jsfiddle.net/jdok2rac/

Great course by the way.

I get this error in your fiddle. “Uncaught ReferenceError: require is not defined”
I cant fix that. I dont know how.

Where is the original example where you discovered this technique of cloning the meshphongmateral into a shader. I know it’s possible , but I don’t know where the information is that you are going by.

Here is where I discovered the the technique

your fiddle doesn’t work full stop. Create an example that shows the actual error that you see.
Line 151 in your error you pasted doesn’t seem to relate to line 151 in your fiddle. try codesandbox maybe. I can never get jsfiddle to work for me.

Hey,

I’ve uploaded part of the project to codesandbox, I’m still getting the error

'Property ‘___’ does not exist on type ‘Shadermaterial’.

I’ve highlighted the lines in client.ts causing this error with ***

Sandbox: https://codesandbox.io/s/interesting-booth-42bx4?file=/src/client/client.ts
Where I’m pulling example from: https://threejs.org/examples/#webgl_gpgpu_water

Thats because,

In your original code
change
const material = new THREE.ShaderMaterial( {
to
var material:any = new THREE.ShaderMaterial( {

That way both the javascript and typescript complier will be happy.

const means you need to be more strict and you can’t just add a new property to material, eg material.color
In the original code, using var material allows this dynamic addition of a property later in the code.

var material:any will tell the TS compiler to ignore that fact you declared it as a shadermaterial and also let you add the color, specular and shininess properties in the next few lines of code.

Here is the original webgl gpgpu water example converted to the more strict version containing lots of lets and consts and types for the variables I could figure out.

1 Like

Thank you!!!