未验证 提交 feefe067 编写于 作者: M Mr.doob 提交者: GitHub

Merge pull request #13717 from takahirox/WebGLRendererWebGL2.0

WebGLRenderer WebGL2.0 initial support with GLSL 1 to 3 runtime conversion
......@@ -18,6 +18,19 @@ var Detector = {
}
} )(),
webgl2: ( function () {
try {
var canvas = document.createElement( 'canvas' ); return !! ( window.WebGL2RenderingContext && ( canvas.getContext( 'webgl2' ) ) );
} catch ( e ) {
return false;
}
} )(),
workers: !! window.Worker,
fileapi: window.File && window.FileReader && window.FileList && window.Blob,
......
......@@ -44,7 +44,7 @@
import { Mesh } from '../src/objects/Mesh.js';
import { Fog } from '../src/scenes/Fog.js';
import { Scene } from '../src/scenes/Scene.js';
import { WebGL2Renderer } from '../src/renderers/WebGL2Renderer.js';
import { WebGLRenderer } from '../src/renderers/WebGLRenderer.js';
//
......@@ -89,7 +89,10 @@
}
renderer = new WebGL2Renderer();
var canvas = document.createElement( 'canvas' );
var context = canvas.getContext( 'webgl2' );
renderer = new WebGLRenderer( { canvas: canvas, context: context } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
......
......@@ -209,6 +209,8 @@ function WebGLRenderer( parameters ) {
}
_gl.isWebGL2 = typeof WebGL2RenderingContext !== 'undefined' && _gl instanceof WebGL2RenderingContext;
// Some experimental-webgl implementations do not have getShaderPrecisionFormat
if ( _gl.getShaderPrecisionFormat === undefined ) {
......@@ -238,14 +240,20 @@ function WebGLRenderer( parameters ) {
function initGLContext() {
extensions = new WebGLExtensions( _gl );
extensions.get( 'WEBGL_depth_texture' );
extensions.get( 'OES_texture_float' );
if ( ! _gl.isWebGL2 ) {
extensions.get( 'WEBGL_depth_texture' );
extensions.get( 'OES_texture_float' );
extensions.get( 'OES_texture_half_float' );
extensions.get( 'OES_texture_half_float_linear' );
extensions.get( 'OES_standard_derivatives' );
extensions.get( 'OES_element_index_uint' );
extensions.get( 'ANGLE_instanced_arrays' );
}
extensions.get( 'OES_texture_float_linear' );
extensions.get( 'OES_texture_half_float' );
extensions.get( 'OES_texture_half_float_linear' );
extensions.get( 'OES_standard_derivatives' );
extensions.get( 'OES_element_index_uint' );
extensions.get( 'ANGLE_instanced_arrays' );
utils = new WebGLUtils( _gl, extensions );
......@@ -806,7 +814,7 @@ function WebGLRenderer( parameters ) {
function setupVertexAttributes( material, program, geometry ) {
if ( geometry && geometry.isInstancedBufferGeometry ) {
if ( geometry && geometry.isInstancedBufferGeometry & ! _gl.isWebGL2 ) {
if ( extensions.get( 'ANGLE_instanced_arrays' ) === null ) {
......@@ -2519,8 +2527,8 @@ function WebGLRenderer( parameters ) {
}
if ( textureType !== UnsignedByteType && utils.convert( textureType ) !== _gl.getParameter( _gl.IMPLEMENTATION_COLOR_READ_TYPE ) && // IE11, Edge and Chrome Mac < 52 (#9513)
! ( textureType === FloatType && ( extensions.get( 'OES_texture_float' ) || extensions.get( 'WEBGL_color_buffer_float' ) ) ) && // Chrome Mac >= 52 and Firefox
! ( textureType === HalfFloatType && extensions.get( 'EXT_color_buffer_half_float' ) ) ) {
! ( textureType === FloatType && ( _gl.isWebGL2 || extensions.get( 'OES_texture_float' ) || extensions.get( 'WEBGL_color_buffer_float' ) ) ) && // Chrome Mac >= 52 and Firefox
! ( textureType === HalfFloatType && ( _gl.isWebGL2 ? extensions.get( 'EXT_color_buffer_float' ) : extensions.get( 'EXT_color_buffer_half_float' ) ) ) ) {
console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.' );
return;
......
......@@ -22,16 +22,26 @@ function WebGLBufferRenderer( gl, extensions, info ) {
function renderInstances( geometry, start, count ) {
var extension = extensions.get( 'ANGLE_instanced_arrays' );
var extension;
if ( extension === null ) {
if ( gl.isWebGL2 ) {
console.error( 'THREE.WebGLBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' );
return;
extension = gl;
} else {
extension = extensions.get( 'ANGLE_instanced_arrays' );
if ( extension === null ) {
console.error( 'THREE.WebGLBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' );
return;
}
}
extension.drawArraysInstancedANGLE( mode, start, count, geometry.maxInstancedCount );
extension[ gl.isWebGL2 ? 'drawArraysInstanced' : 'drawArraysInstancedANGLE' ]( mode, start, count, geometry.maxInstancedCount );
info.update( count, mode, geometry.maxInstancedCount );
......
......@@ -79,7 +79,7 @@ function WebGLCapabilities( gl, extensions, parameters ) {
var maxFragmentUniforms = gl.getParameter( gl.MAX_FRAGMENT_UNIFORM_VECTORS );
var vertexTextures = maxVertexTextures > 0;
var floatFragmentTextures = !! extensions.get( 'OES_texture_float' );
var floatFragmentTextures = gl.isWebGL2 || !! extensions.get( 'OES_texture_float' );
var floatVertexTextures = vertexTextures && floatFragmentTextures;
return {
......
......@@ -31,16 +31,26 @@ function WebGLIndexedBufferRenderer( gl, extensions, info ) {
function renderInstances( geometry, start, count ) {
var extension = extensions.get( 'ANGLE_instanced_arrays' );
var extension;
if ( extension === null ) {
if ( gl.isWebGL2 ) {
console.error( 'THREE.WebGLIndexedBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' );
return;
extension = gl;
} else {
var extension = extensions.get( 'ANGLE_instanced_arrays' );
if ( extension === null ) {
console.error( 'THREE.WebGLIndexedBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' );
return;
}
}
extension.drawElementsInstancedANGLE( mode, count, type, start * bytesPerElement, geometry.maxInstancedCount );
extension[ gl.isWebGL2 ? 'drawElementsInstanced' : 'drawElementsInstancedANGLE' ]( mode, count, type, start * bytesPerElement, geometry.maxInstancedCount );
info.update( count, mode, geometry.maxInstancedCount );
......
......@@ -285,7 +285,7 @@ function WebGLProgram( renderer, extensions, code, material, shader, parameters
//
var customExtensions = generateExtensions( material.extensions, parameters, extensions );
var customExtensions = gl.isWebGL2 ? '' : generateExtensions( material.extensions, parameters, extensions );
var customDefines = generateDefines( defines );
......@@ -373,7 +373,7 @@ function WebGLProgram( renderer, extensions, code, material, shader, parameters
parameters.sizeAttenuation ? '#define USE_SIZEATTENUATION' : '',
parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '',
parameters.logarithmicDepthBuffer && extensions.get( 'EXT_frag_depth' ) ? '#define USE_LOGDEPTHBUF_EXT' : '',
parameters.logarithmicDepthBuffer && ( gl.isWebGL2 || extensions.get( 'EXT_frag_depth' ) ) ? '#define USE_LOGDEPTHBUF_EXT' : '',
'uniform mat4 modelMatrix;',
'uniform mat4 modelViewMatrix;',
......@@ -478,9 +478,9 @@ function WebGLProgram( renderer, extensions, code, material, shader, parameters
parameters.physicallyCorrectLights ? '#define PHYSICALLY_CORRECT_LIGHTS' : '',
parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '',
parameters.logarithmicDepthBuffer && extensions.get( 'EXT_frag_depth' ) ? '#define USE_LOGDEPTHBUF_EXT' : '',
parameters.logarithmicDepthBuffer && ( gl.isWebGL2 || extensions.get( 'EXT_frag_depth' ) ) ? '#define USE_LOGDEPTHBUF_EXT' : '',
parameters.envMap && extensions.get( 'EXT_shader_texture_lod' ) ? '#define TEXTURE_LOD_EXT' : '',
parameters.envMap && ( gl.isWebGL2 || extensions.get( 'EXT_shader_texture_lod' ) ) ? '#define TEXTURE_LOD_EXT' : '',
'uniform mat4 viewMatrix;',
'uniform vec3 cameraPosition;',
......@@ -516,6 +516,50 @@ function WebGLProgram( renderer, extensions, code, material, shader, parameters
vertexShader = unrollLoops( vertexShader );
fragmentShader = unrollLoops( fragmentShader );
if ( gl.isWebGL2 && ! material.isRawShaderMaterial ) {
var isGLSL3ShaderMaterial = false;
var versionRegex = /^\s*#version\s+300\s+es\s*\n/;
if ( material.isShaderMaterial &&
vertexShader.match( versionRegex ) !== null &&
fragmentShader.match( versionRegex ) !== null ) {
isGLSL3ShaderMaterial = true;
vertexShader = vertexShader.replace( versionRegex, '' );
fragmentShader = fragmentShader.replace( versionRegex, '' );
}
// GLSL 3.0 conversion
prefixVertex = [
'#version 300 es\n',
'#define attribute in',
'#define varying out',
'#define texture2D texture'
].join( '\n' ) + '\n' + prefixVertex;
prefixFragment = [
'#version 300 es\n',
'#define varying in',
isGLSL3ShaderMaterial ? '' : 'out highp vec4 pc_fragColor;',
isGLSL3ShaderMaterial ? '' : '#define gl_FragColor pc_fragColor',
'#define gl_FragDepthEXT gl_FragDepth',
'#define texture2D texture',
'#define textureCube texture',
'#define texture2DProj textureProj',
'#define texture2DLodEXT textureLod',
'#define texture2DProjLodEXT textureProjLod',
'#define textureCubeLodEXT textureLod',
'#define texture2DGradEXT textureGrad',
'#define texture2DProjGradEXT textureProjGrad',
'#define textureCubeGradEXT textureGrad'
].join( '\n' ) + '\n' + prefixFragment;
}
var vertexGlsl = prefixVertex + vertexShader;
var fragmentGlsl = prefixFragment + fragmentShader;
......
......@@ -434,9 +434,9 @@ function WebGLState( gl, extensions, utils ) {
if ( attributeDivisors[ attribute ] !== meshPerAttribute ) {
var extension = extensions.get( 'ANGLE_instanced_arrays' );
var extension = gl.isWebGL2 ? gl : extensions.get( 'ANGLE_instanced_arrays' );
extension.vertexAttribDivisorANGLE( attribute, meshPerAttribute );
extension[ gl.isWebGL2 ? 'vertexAttribDivisor' : 'vertexAttribDivisorANGLE' ]( attribute, meshPerAttribute );
attributeDivisors[ attribute ] = meshPerAttribute;
}
......
......@@ -7,7 +7,6 @@ import { _Math } from '../../math/Math.js';
function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info ) {
var _isWebGL2 = ( typeof WebGL2RenderingContext !== 'undefined' && _gl instanceof WebGL2RenderingContext ); /* global WebGL2RenderingContext */
var _videoTextures = {};
var _canvas;
......@@ -76,6 +75,8 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
function textureNeedsPowerOfTwo( texture ) {
if ( _gl.isWebGL2 ) return false;
return ( texture.wrapS !== ClampToEdgeWrapping || texture.wrapT !== ClampToEdgeWrapping ) ||
( texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter );
......@@ -99,6 +100,30 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
}
function getInternalFormat( glFormat, glType ) {
if ( ! _gl.isWebGL2 ) return glFormat;
if ( glFormat === _gl.RGB ) {
if ( glType === _gl.FLOAT ) return _gl.RGB32F;
if ( glType === _gl.HALF_FLOAT ) return _gl.RGB16F;
if ( glType === _gl.UNSIGNED_BYTE ) return _gl.RGB8;
}
if ( glFormat === _gl.RGBA ) {
if ( glType === _gl.FLOAT ) return _gl.RGBA32F;
if ( glType === _gl.HALF_FLOAT ) return _gl.RGBA16F;
if ( glType === _gl.UNSIGNED_BYTE ) return _gl.RGBA8;
}
return glFormat;
}
// Fallback filters for non-power-of-2 textures
function filterFallback( f ) {
......@@ -293,7 +318,8 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
var image = cubeImage[ 0 ],
isPowerOfTwoImage = isPowerOfTwo( image ),
glFormat = utils.convert( texture.format ),
glType = utils.convert( texture.type );
glType = utils.convert( texture.type ),
glInternalFormat = getInternalFormat( glFormat, glType );
setTextureParameters( _gl.TEXTURE_CUBE_MAP, texture, isPowerOfTwoImage );
......@@ -303,11 +329,11 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
if ( isDataTexture ) {
state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glFormat, cubeImage[ i ].width, cubeImage[ i ].height, 0, glFormat, glType, cubeImage[ i ].data );
state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, cubeImage[ i ].width, cubeImage[ i ].height, 0, glFormat, glType, cubeImage[ i ].data );
} else {
state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glFormat, glFormat, glType, cubeImage[ i ] );
state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, glFormat, glType, cubeImage[ i ] );
}
......@@ -323,7 +349,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
if ( state.getCompressedTextureFormats().indexOf( glFormat ) > - 1 ) {
state.compressedTexImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glFormat, mipmap.width, mipmap.height, 0, mipmap.data );
state.compressedTexImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data );
} else {
......@@ -333,7 +359,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
} else {
state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
}
......@@ -421,7 +447,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
if ( extension ) {
if ( texture.type === FloatType && extensions.get( 'OES_texture_float_linear' ) === null ) return;
if ( texture.type === HalfFloatType && extensions.get( 'OES_texture_half_float_linear' ) === null ) return;
if ( texture.type === HalfFloatType && ( _gl.isWebGL2 || extensions.get( 'OES_texture_half_float_linear' ) ) === null ) return;
if ( texture.anisotropy > 1 || properties.get( texture ).__currentAnisotropy ) {
......@@ -465,7 +491,8 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
var isPowerOfTwoImage = isPowerOfTwo( image ),
glFormat = utils.convert( texture.format ),
glType = utils.convert( texture.type );
glType = utils.convert( texture.type ),
glInternalFormat = getInternalFormat( glFormat, glType );
setTextureParameters( _gl.TEXTURE_2D, texture, isPowerOfTwoImage );
......@@ -475,21 +502,21 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
// populate depth texture with dummy data
var internalFormat = _gl.DEPTH_COMPONENT;
glInternalFormat = _gl.DEPTH_COMPONENT;
if ( texture.type === FloatType ) {
if ( ! _isWebGL2 ) throw new Error( 'Float Depth Texture only supported in WebGL2.0' );
internalFormat = _gl.DEPTH_COMPONENT32F;
if ( ! _gl.isWebGL2 ) throw new Error( 'Float Depth Texture only supported in WebGL2.0' );
glInternalFormat = _gl.DEPTH_COMPONENT32F;
} else if ( _isWebGL2 ) {
} else if ( _gl.isWebGL2 ) {
// WebGL 2.0 requires signed internalformat for glTexImage2D
internalFormat = _gl.DEPTH_COMPONENT16;
glInternalFormat = _gl.DEPTH_COMPONENT16;
}
if ( texture.format === DepthFormat && internalFormat === _gl.DEPTH_COMPONENT ) {
if ( texture.format === DepthFormat && glInternalFormat === _gl.DEPTH_COMPONENT ) {
// The error INVALID_OPERATION is generated by texImage2D if format and internalformat are
// DEPTH_COMPONENT and type is not UNSIGNED_SHORT or UNSIGNED_INT
......@@ -509,7 +536,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
// (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)
if ( texture.format === DepthStencilFormat ) {
internalFormat = _gl.DEPTH_STENCIL;
glInternalFormat = _gl.DEPTH_STENCIL;
// The error INVALID_OPERATION is generated by texImage2D if format and internalformat are
// DEPTH_STENCIL and type is not UNSIGNED_INT_24_8_WEBGL.
......@@ -525,7 +552,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
}
state.texImage2D( _gl.TEXTURE_2D, 0, internalFormat, image.width, image.height, 0, glFormat, glType, null );
state.texImage2D( _gl.TEXTURE_2D, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, null );
} else if ( texture.isDataTexture ) {
......@@ -538,7 +565,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
for ( var i = 0, il = mipmaps.length; i < il; i ++ ) {
mipmap = mipmaps[ i ];
state.texImage2D( _gl.TEXTURE_2D, i, glFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
state.texImage2D( _gl.TEXTURE_2D, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
}
......@@ -547,7 +574,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
} else {
state.texImage2D( _gl.TEXTURE_2D, 0, glFormat, image.width, image.height, 0, glFormat, glType, image.data );
state.texImage2D( _gl.TEXTURE_2D, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, image.data );
textureProperties.__maxMipLevel = 0;
}
......@@ -562,7 +589,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
if ( state.getCompressedTextureFormats().indexOf( glFormat ) > - 1 ) {
state.compressedTexImage2D( _gl.TEXTURE_2D, i, glFormat, mipmap.width, mipmap.height, 0, mipmap.data );
state.compressedTexImage2D( _gl.TEXTURE_2D, i, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data );
} else {
......@@ -572,7 +599,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
} else {
state.texImage2D( _gl.TEXTURE_2D, i, glFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
state.texImage2D( _gl.TEXTURE_2D, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
}
......@@ -593,7 +620,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
for ( var i = 0, il = mipmaps.length; i < il; i ++ ) {
mipmap = mipmaps[ i ];
state.texImage2D( _gl.TEXTURE_2D, i, glFormat, glFormat, glType, mipmap );
state.texImage2D( _gl.TEXTURE_2D, i, glInternalFormat, glFormat, glType, mipmap );
}
......@@ -602,7 +629,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
} else {
state.texImage2D( _gl.TEXTURE_2D, 0, glFormat, glFormat, glType, image );
state.texImage2D( _gl.TEXTURE_2D, 0, glInternalFormat, glFormat, glType, image );
textureProperties.__maxMipLevel = 0;
}
......@@ -628,7 +655,8 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
var glFormat = utils.convert( renderTarget.texture.format );
var glType = utils.convert( renderTarget.texture.type );
state.texImage2D( textureTarget, 0, glFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null );
var glInternalFormat = getInternalFormat( glFormat, glType );
state.texImage2D( textureTarget, 0, glInternalFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null );
_gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
_gl.framebufferTexture2D( _gl.FRAMEBUFFER, attachment, textureTarget, properties.get( renderTarget.texture ).__webglTexture, 0 );
_gl.bindFramebuffer( _gl.FRAMEBUFFER, null );
......
......@@ -36,6 +36,8 @@ function WebGLUtils( gl, extensions ) {
if ( p === HalfFloatType ) {
if ( gl.isWebGL2 ) return gl.HALF_FLOAT;
extension = extensions.get( 'OES_texture_half_float' );
if ( extension !== null ) return extension.HALF_FLOAT_OES;
......@@ -125,6 +127,13 @@ function WebGLUtils( gl, extensions ) {
if ( p === MinEquation || p === MaxEquation ) {
if ( gl.isWebGL2 ) {
if ( p === MinEquation ) return gl.MIN;
if ( p === MaxEquation ) return gl.MAX;
}
extension = extensions.get( 'EXT_blend_minmax' );
if ( extension !== null ) {
......@@ -138,6 +147,8 @@ function WebGLUtils( gl, extensions ) {
if ( p === UnsignedInt248Type ) {
if ( gl.isWebGL2 ) return gl.UNSIGNED_INT_24_8;
extension = extensions.get( 'WEBGL_depth_texture' );
if ( extension !== null ) return extension.UNSIGNED_INT_24_8_WEBGL;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册