mrdoob / three.js

JavaScript 3D Library.
https://threejs.org/
MIT License
102.81k stars 35.38k forks source link

Error Webgl whilst implementing in React #19988

Closed Arshazar closed 4 years ago

Arshazar commented 4 years ago

this is my code:

import * as THREE from "three"
import {TweenLite, Power4} from "gsap"

export function projectsAnimations () {
    //VARIABLES
    let itemsWrapper = document.querySelector('.grid')
    let options = {}
    let isLoaded = false
    let mouse
    let timeSpeed
    let time
    let clock
    let container = document.body
    //VIEW PORT
    const viewport = {
        width: container.clientWidth,
        height: container.clientHeight,
        aspectRatio: container.clientWidth / container.clientHeight
    }
    //MATH
    Number.prototype.map = function(in_min, in_max, out_min, out_max) {
        return ((this - in_min) * (out_max - out_min)) / (in_max - in_min) + out_min
    }

    window.addEventListener('resize', onWindowResize.bind(this), false)
    let renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true })
    renderer.setSize(viewport.width, viewport.height)
    renderer.setPixelRatio(window.devicePixelRatio)
    container.appendChild(renderer.domElement)
    let scene = new THREE.Scene()
    let camera = new THREE.PerspectiveCamera(
        40,
        viewport.aspectRatio,
        0.1,
        100
    )
    camera.position.set(0, 0, 3)

    mouse = new THREE.Vector2()

    //TIME
    timeSpeed = 2
    time = 0
    clock = new THREE.Clock()
    //...............render.............
    function render() {
        // called every frame
        time += clock.getDelta() * timeSpeed
        renderer.render(scene, camera)
    }
    renderer.setAnimationLoop(render.bind(this))

    //...........ITEMS..............
    // const items = Array.prototype.slice.call(document.querySelectorAll('.link'))
    let items = [...itemsWrapper.querySelectorAll('.link')]
    items = items.map((item, index) => ({
        element: item,
        img: item.querySelector('img') || null,
        index: index
    }))
    //...................................

    function initEffectShell() {
        let promises = []

        const THREEtextureLoader = new THREE.TextureLoader()

        items.forEach((item, index) => {
            // create textures
            promises.push(
                loadTexture(
                    THREEtextureLoader,
                    item.img ? item.img.src : null,
                    index
                )
            )
        })

        return new Promise((resolve, reject) => {
            // resolve textures promises
            Promise.all(promises).then(promises => {
                // all textures are loaded
                promises.forEach((promise, index) => {
                    // assign texture to item
                    items[index].texture = promise.texture
                })
                resolve()
            })
        })
    }

    initEffectShell().then(() => {
        console.log('load finished')
        isLoaded = true
    })

    //..........EVENT LISTENERS..............
    let tempItemIndex
    let isMouseOver
    let currentItem

    //VIEW SIZE
    let distance = camera.position.z
    let vFov = (camera.fov * Math.PI) / 180
    const viewSize = {
        width: 2 * Math.tan(vFov / 2) * distance * viewport.aspectRatio,
        height: 2 * Math.tan(vFov / 2) * distance, vFov
    }

    items.forEach((item, index) => {
        item.element.addEventListener(
            'mouseover',
            _onMouseOver.bind(this, index),
            false
        )
    })

    container.addEventListener(
        'mousemove',
        _onMouseMove.bind(this),
        false
    )
    itemsWrapper.addEventListener(
        'mouseleave',
        _onMouseLeave.bind(this),
        false
    )

    function _onMouseLeave(event) {
        isMouseOver = false
        onMouseLeave(event)
    }

    function _onMouseMove(event) {
        // get normalized mouse position on viewport
        mouse.x = (event.clientX / viewport.width) * 2 - 1
        mouse.y = -(event.clientY / viewport.height) * 2 + 1

        onMouseMove(event)
    }

    function _onMouseOver(index, event) {
        tempItemIndex = index

        onMouseOver(index, event)
    }

    //.............resize............
    function onWindowResize() {
        camera.aspect = viewport.aspectRatio
        camera.updateProjectionMatrix()
        renderer.setSize(viewport.width, viewport.height)
    }

    //......UPDATE TEXTURE..........
    function onMouseEnter() {
        if (!currentItem || !isMouseOver) {
            isMouseOver = true
            // show plane
            TweenLite.to(uniforms.uAlpha, 0.5, {
                value: 1,
                ease: Power4.easeOut
            })
        }
    }

    function onMouseLeave(event) {
        TweenLite.to(uniforms.uAlpha, 0.5, {
            value: 0,
            ease: Power4.easeOut
        })
    }

    function onMouseMove(event) {
        // project mouse position to world coodinates
        let x = mouse.x.map(
            -1,
            1,
            -viewSize.width / 2,
            viewSize.width / 2
        )
        let y = mouse.y.map(
            -1,
            1,
            -viewSize.height / 2,
            viewSize.height / 2
        )

        position = new THREE.Vector3(x, y, 0)
        TweenLite.to(plane.position, 1, {
            x: x,
            y: y,
            ease: Power4.easeOut,
            onUpdate: onPositionUpdate.bind(this)
        })
    }

    function onTargetChange(index) {
        // item target changed
        currentItem = items[index]
        if (!currentItem.texture) return

        // compute image ratio
        let imageRatio =
            currentItem.img.naturalWidth / currentItem.img.naturalHeight
        scale = new THREE.Vector3(imageRatio, 1, 1)
        uniforms.uTexture.value = currentItem.texture
        plane.scale.copy(scale)
    }

    function onMouseOver(index, e) {
        if (!isLoaded) return
        onMouseEnter()
        if (currentItem && currentItem.index === index) return
        onTargetChange(index)
    }

    function onPositionUpdate() {
        // compute offset
        uniforms.uOffset.value = plane.position
            .clone()
            .sub(position)
            .multiplyScalar(-options.strength)
    }

    //..........LOAD TEXTURE.......
    function loadTexture(loader, url, index) {
        // https://threejs.org/docs/#api/en/loaders/TextureLoader
        return new Promise((resolve, reject) => {
            if (!url) {
                resolve({ texture: null, index })
                return
            }
            // load a resource
            loader.load(
                // resource URL
                url,

                // onLoad callback
                texture => {
                    resolve({ texture, index })
                },

                // onProgress callback currently not supported
                undefined,

                // onError callback
                error => {
                    console.error('An error happened.', error)
                    reject(error)
                }
            )
        })
    }

    //..........INIT..............
    options.strength = options.strength || 0.25

    let position = new THREE.Vector3(0, 0, 0)
    let scale = new THREE.Vector3(1, 1, 1)
    let geometry = new THREE.PlaneBufferGeometry(1, 1, 32, 32)
    let uniforms = {
        uTime: {
            value: 0
        },
        uTexture: {
            value: null
        },
        uOffset: {
            value: new THREE.Vector2(0.0, 0.0)
        },
        uAlpha: {
            value: 0
        }
    }
    let material = new THREE.ShaderMaterial({
        uniforms: uniforms,
        vertexShader: `
                uniform vec2 uOffset;
                varying vec2 vUv;
                vec3 deformationCurve(vec3 position, vec2 uv, vec2 offset) {
                  float M_PI = 3.1415926535897932384626433832795;
                  position.x = position.x + (sin(uv.y * M_PI) * offset.x);
                  position.y = position.y + (sin(uv.x * M_PI) * offset.y);
                  return position;
                }

                void main() {
                  vUv = uv;
                  vec3 newPosition = position;
                  newPosition = deformationCurve(position,uv,uOffset);
                  gl_Position = projectionMatrix * modelViewMatrix * vec4( newPosition, 1.0 );
                }
              `,
        fragmentShader: `
                uniform sampler2D uTexture;
                uniform float uAlpha;
                uniform vec2 uOffset;
                varying vec2 vUv;
                vec3 rgbShift(sampler2D texture, vec2 uv, vec2 offset) {
                  float r = texture2D(uTexture,vUv + uOffset).r;
                  vec2 gb = texture2D(uTexture,vUv).gb;
                  return vec3(r,gb);
                }
                void main() {
                  vec3 color = rgbShift(uTexture,vUv,uOffset);
                  gl_FragColor = vec4(color,uAlpha);
                }
              `,
        transparent: true
    })
    let plane = new THREE.Mesh(geometry, material)
    scene.add(plane)
}

Error on console:

THREE.WebGLProgram: shader error:  0 35715 false gl.getProgramInfoLog invalid shaders�  THREE.WebGLShader: gl.getShaderInfoLog() fragment
ERROR: 0:95: 'texture' : function name expected
ERROR: 0:95: 'r' :  field selection requires structure, vector, or interface block on left hand side
ERROR: 0:96: 'texture' : function name expected
ERROR: 0:96: 'gb' :  field selection requires structure, vector, or interface block on left hand side
ERROR: 0:96: '=' : dimension mismatch
ERROR: 0:96: '=' : cannot convert from 'const mediump float' to 'highp 2-component vector of float'
�1: #version 300 es
2: 
3: #define varying in
4: out highp vec4 pc_fragColor;
5: #define gl_FragColor pc_fragColor
6: #define gl_FragDepthEXT gl_FragDepth
7: #define texture2D texture
8: #define textureCube texture
9: #define texture2DProj textureProj
10: #define texture2DLodEXT textureLod
11: #define texture2DProjLodEXT textureProjLod
12: #define textureCubeLodEXT textureLod
13: #define texture2DGradEXT textureGrad
14: #define texture2DProjGradEXT textureProjGrad
15: #define textureCubeGradEXT textureGrad
16: precision highp float;
17: precision highp int;
18: #define HIGH_PRECISION
19: #define SHADER_NAME ShaderMaterial
20: #define GAMMA_FACTOR 2
21: uniform mat4 viewMatrix;
22: uniform vec3 cameraPosition;
23: uniform bool isOrthographic;
24: 
25: vec4 LinearToLinear( in vec4 value ) {
26:     return value;
27: }
28: vec4 GammaToLinear( in vec4 value, in float gammaFactor ) {
29:     return vec4( pow( value.rgb, vec3( gammaFactor ) ), value.a );
30: }
31: vec4 LinearToGamma( in vec4 value, in float gammaFactor ) {
32:     return vec4( pow( value.rgb, vec3( 1.0 / gammaFactor ) ), value.a );
33: }
34: vec4 sRGBToLinear( in vec4 value ) {
35:     return vec4( mix( pow( value.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), value.rgb * 0.0773993808, vec3( lessThanEqual( value.rgb, vec3( 0.04045 ) ) ) ), value.a );
36: }
37: vec4 LinearTosRGB( in vec4 value ) {
38:     return vec4( mix( pow( value.rgb, vec3( 0.41666 ) ) * 1.055 - vec3( 0.055 ), value.rgb * 12.92, vec3( lessThanEqual( value.rgb, vec3( 0.0031308 ) ) ) ), value.a );
39: }
40: vec4 RGBEToLinear( in vec4 value ) {
41:     return vec4( value.rgb * exp2( value.a * 255.0 - 128.0 ), 1.0 );
42: }
43: vec4 LinearToRGBE( in vec4 value ) {
44:     float maxComponent = max( max( value.r, value.g ), value.b );
45:     float fExp = clamp( ceil( log2( maxComponent ) ), -128.0, 127.0 );
46:     return vec4( value.rgb / exp2( fExp ), ( fExp + 128.0 ) / 255.0 );
47: }
48: vec4 RGBMToLinear( in vec4 value, in float maxRange ) {
49:     return vec4( value.rgb * value.a * maxRange, 1.0 );
50: }
51: vec4 LinearToRGBM( in vec4 value, in float maxRange ) {
52:     float maxRGB = max( value.r, max( value.g, value.b ) );
53:     float M = clamp( maxRGB / maxRange, 0.0, 1.0 );
54:     M = ceil( M * 255.0 ) / 255.0;
55:     return vec4( value.rgb / ( M * maxRange ), M );
56: }
57: vec4 RGBDToLinear( in vec4 value, in float maxRange ) {
58:     return vec4( value.rgb * ( ( maxRange / 255.0 ) / value.a ), 1.0 );
59: }
60: vec4 LinearToRGBD( in vec4 value, in float maxRange ) {
61:     float maxRGB = max( value.r, max( value.g, value.b ) );
62:     float D = max( maxRange / maxRGB, 1.0 );
63:     D = clamp( floor( D ) / 255.0, 0.0, 1.0 );
64:     return vec4( value.rgb * ( D * ( 255.0 / maxRange ) ), D );
65: }
66: const mat3 cLogLuvM = mat3( 0.2209, 0.3390, 0.4184, 0.1138, 0.6780, 0.7319, 0.0102, 0.1130, 0.2969 );
67: vec4 LinearToLogLuv( in vec4 value )  {
68:     vec3 Xp_Y_XYZp = cLogLuvM * value.rgb;
69:     Xp_Y_XYZp = max( Xp_Y_XYZp, vec3( 1e-6, 1e-6, 1e-6 ) );
70:     vec4 vResult;
71:     vResult.xy = Xp_Y_XYZp.xy / Xp_Y_XYZp.z;
72:     float Le = 2.0 * log2(Xp_Y_XYZp.y) + 127.0;
73:     vResult.w = fract( Le );
74:     vResult.z = ( Le - ( floor( vResult.w * 255.0 ) ) / 255.0 ) / 255.0;
75:     return vResult;
76: }
77: const mat3 cLogLuvInverseM = mat3( 6.0014, -2.7008, -1.7996, -1.3320, 3.1029, -5.7721, 0.3008, -1.0882, 5.6268 );
78: vec4 LogLuvToLinear( in vec4 value ) {
79:     float Le = value.z * 255.0 + value.w;
80:     vec3 Xp_Y_XYZp;
81:     Xp_Y_XYZp.y = exp2( ( Le - 127.0 ) / 2.0 );
82:     Xp_Y_XYZp.z = Xp_Y_XYZp.y / value.y;
83:     Xp_Y_XYZp.x = value.x * Xp_Y_XYZp.z;
84:     vec3 vRGB = cLogLuvInverseM * Xp_Y_XYZp.rgb;
85:     return vec4( max( vRGB, 0.0 ), 1.0 );
86: }
87: vec4 linearToOutputTexel( vec4 value ) { return LinearToLinear( value ); }
88: 
89: 
90:                 uniform sampler2D uTexture;
91:                 uniform float uAlpha;
92:                 uniform vec2 uOffset;
93:                 varying vec2 vUv;
94:                 vec3 rgbShift(sampler2D texture, vec2 uv, vec2 offset) {
95:                   float r = texture2D(uTexture,vUv + uOffset).r;
96:                   vec2 gb = texture2D(uTexture,vUv).gb;
97:                   return vec3(r,gb);
98:                 }
99:                 void main() {
100:                   vec3 color = rgbShift(uTexture,vUv,uOffset);
101:                   gl_FragColor = vec4(color,uAlpha);
102:                 }
103:               `
with some warnings: 
`WebGL: INVALID_OPERATION: useProgram: program not valid
WebGL: INVALID_OPERATION: drawElements: no valid shader program in use
WebGL: too many errors, no more errors will be reported to the console for this context.
`

I tried to use [this](https://github.com/clementroche/motion-hover-effects) first effect in react, in terminal I see no error, but in console, there is. 
I can see the demo website with no problem [here](https://tympanus.net/Tutorials/MotionHoverEffects/)

in my package.json:
` "dependencies": {
    "framer-motion": "^2.3.0",
    "gatsby": "^2.23.12",
    "gatsby-image": "^2.4.9",
    "gatsby-plugin-manifest": "^2.4.14",
    "gatsby-plugin-offline": "^3.2.13",
    "gatsby-plugin-react-helmet": "^3.3.6",
    "gatsby-plugin-sass": "^2.3.12",
    "gatsby-plugin-sharp": "^2.6.14",
    "gatsby-source-filesystem": "^2.3.14",
    "gatsby-transformer-sharp": "^2.5.7",
    "gsap": "^3.4.2",
    "imagesloaded": "^4.1.4",
    "locomotive-scroll": "^3.5.4",
    "node-sass": "^4.14.1",
    "prop-types": "^15.7.2",
    "react": "^16.12.0",
    "react-dom": "^16.12.0",
    "react-gsap": "^2.2.1",
    "react-helmet": "^6.1.0",
    "react-router-dom": "^5.2.0",
    "three": "^0.119.1"
  },
Browser

My System: OS : linux mint 19 (ubuntu based) GPU: [AMD/ATI] Richland [Radeon HD 8650G] RAM : 14.8GB

mrdoob commented 4 years ago

Please, use the forum or the chat for help.