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
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgl - gpgpu - water</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<link type="text/css" rel="stylesheet" href="main.css">
</head>
<body>
<div id="info">
<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> - <span id="waterSize"></span> webgl gpgpu water<br/>
Move mouse to disturb water.<br>
Press mouse button to orbit around. 'W' key toggles wireframe.
</div>
<!-- This is the 'compute shader' for the water heightmap: -->
<script id="heightmapFragmentShader" type="x-shader/x-fragment">
This file has been truncated. show original
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: interesting-booth-42bx4 - CodeSandbox
Where I’m pulling example from: three.js examples
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.
webgl gpgpu water example in TypeScript by Sean-Bradley using @types/dat.gui, @types/express, express, three, typescript
1 Like