aframe实现三维玻璃立方体视差着色器代码

代码语言:html

所属分类:三维

代码描述:aframe实现三维玻璃立方体视差着色器代码

代码标签: aframe 三维 玻璃 立方体 视差 着色器 代码

下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开

<!DOCTYPE html>
<html lang="en" >

<head>

  <meta charset="UTF-8">

  <meta name="viewport" content="width=device-width, initial-scale=1">
<script>console.clear();</script>
<script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/aframe.1.3.0.js"></script>
<script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/aframe-orbit-controls.1.3.0.js"></script>


  
  
<style>
.tip {
  position: fixed;
  top: 4px;
  z-index: 1;
  pointer-events: none;
  width: 100%;
  padding: 12px;
  font-family: system-ui, sans-serif;
  font-size: clamp(0.75rem, 3.5vw, 1.25rem);
  text-align: center;
  color: #fff;
  opacity: 0.25;
}
</style>




</head>

<body  >
  <script>

AFRAME.registerComponent('glass-cube', {
  schema: {},
  init() {
		const mesh = this.el.getObject3D('mesh');
		mesh.geometry.computeTangents();
		mesh.material = this.generateMaterial();
	},
	generateMaterial() {
		const colorTex = new THREE.TextureLoader().load('//repo.bfw.wiki/bfwrepo/images/cube/colored_squares.png');
		const normalTex = new THREE.TextureLoader().load('//repo.bfw.wiki/bfwrepo/images/cube/glass_frosted_normal_tex.jpg');
		// const normalTex = new THREE.TextureLoader().load('//repo.bfw.wiki/bfwrepo/images/cube/tiles_normal_map.jpg');
		return new THREE.ShaderMaterial({
			uniforms: {
				u_colorTex: { type: 't', value: colorTex },
				u_normalTex: { type: 't', value: normalTex }
			},
			// I learned a lot about normal/parallax mapping from this article + demo:
			// https://apoorvaj.io/exploring-bump-mapping-with-webgl/
			vertexShader: `
				// THREE doesn't seem to add the "tangent" attribute automatically when we compute the tangents.
				// The attribute data is there, we just need to declare it here.
				attribute vec4 tangent;
				
				varying vec3 v_normal;
				varying vec2 v_uv;
				varying vec3 v_fragPos;
				varying vec3 v_viewPos;
				varying vec3 v_lightPos;

				void main() {
					// Compute the bitangent at runtime - it's not too expensive per-vertex.
					// Often this is another vertex attribute, but "BufferGeometry.computeTangents()" doesn't store it as an attribute.
					// For now, I didn't feel like figuring out the best way to compute these on the CPU, but it could be done :)
					vec3 bitangent = cross(normal, tangent.xyz);
					
					// Now that we have all three tangent space basis vectors, transform them to align with the model transform.
					vec3 t = normalize(normalMatrix * tangent.xyz);
					vec3 b = normalize(normalMatrix * bitangent);
					vec3 n = normalize(normalMatrix * normal);
					// Finally, generate a 3x3 matrix that converts from world space to tangent space.
					// Apparently the base matrix goes from tangent space to world space, and to go the other direction
					// we have to take the inverse of it. However, since we don't have any shearing/skewing happening,
					// an equivalent operation is the transpose, which is faster. If this doesn't work for a future project,
					// just be aware that what we really need might be an inverse 3x3 matrix function.
					// I didn't know there is a built-in transpose function, but we get an error if we define our own.
					// Maybe threejs is providing this? If there are ever any errors porting this code (e.g. to regl),
					// we may need to define a custom transpose() - I have an implementation commented up above.
					mat3 tbn = transpose(mat3(t, b, n));
					
					// The following code is designed to work in world space.
					// However it turns out the normalMatrix three.js provides is based on the modelViewMatrix, not just the modelMatrix.
					// So, we actually need to convert everything into view space, not world space, to be compatible with the given normalMatrix.
					// If I ever build a similar system myself, I may use a world-relative normal matrix and world space coordinates.
					// ------------------------------------------------------
					// vec3 vertPositionWorld = (modelMatrix * vec4(position, 1.0)).xyz;
					// vec3 lightPosWorld = vec3(1.0, 4.0, 0.0);
					// v_uv = uv;
					// v_fragPos = tbn * vertPositionWorld;
					// v_viewPos = tbn * cameraPosition;
					// v_lightPos = tbn * lightPosWorld;
					
					// FIXED VERSION CONVERTING EVERYTHING TO VIEW SPACE
					// ------------------------------------------------------
					vec3 vertPositionView = (modelViewMatrix * vec4(position, 1.0)).xyz;
					vec3 lightPosWorld = vec3(1.0, 4.0, 0.0);
					vec3 lightPosView = (viewMatrix * vec4(lightPosWorld, 1.0)).xyz;
					
					// Local UV coordinates should not be modified.
					v_uv = uv;
					// All world space values must be transformed into tangent space.
					v_fragPos = tbn * vertPositionView;
					v_viewPos = vec3(0.0, 0.0, 0.0); // in view space, camera is always at (0, 0, 0)
					v_lightPos = tbn * lightPosView;
					
					gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
				}
			`,
			fragmentShader: `
				uniform sampler2D u_colorTex;
				uniform sampler2D u_normalTex;
				
				varying vec2 v_uv;
				varying vec3 v_fragPos;
				varying vec3 v_viewPos;
				varying vec3 v_lightPos;

		
				/**
				 * Lighting contribution of a single point light source via Phong illumination.
				 * 
				 * The vec3 returned is the RGB color of the light's contribution.
				 *
				 * k_d: Diffuse color
				 * k_s: Specular color
				 * alpha: Shininess coefficient
				 * p: position of point being lit
				 * n: normal of point being lit
				 * eye: the position of the camera
				 * lightPos: the position of the light
				 * lightIntensity: color/intensity of the light
				 *
				 * See https://en.wikipedia.org/wiki/Phong_reflection_model#Description
				 */
				vec3 phongContribForLight(vec3 k_d, vec3 k_s, float alpha, vec3 p, vec3 n, vec3 eye, vec3 lightPos, vec3 lightIntensity) {
					vec3 N = n;
					vec3 L = normalize(lightPos - p);
					vec3 V = normalize(eye - p);
					vec3 R = normalize(reflect(-L, N));

					float dotLN = dot(L, N);
					float dotRV = dot(R, V);

					if (dotLN < 0.0) {
						// Light not visible from this point on the surface
						return vec3(0.0, 0.0, 0.0);
					}

					// Clamp added to prevent harsh lighting transitions at high reflection angles
					dotLN = clamp(dotLN, 0.0, 1.0);

					if (dotRV < 0.0) {
						// Light reflection in opposite direction as viewer, apply only diffuse component
						return lightIntensity * (k_d * dotLN);
					}
					return lightIntensity * (k_d * dotLN + k_s * pow(dotRV, alpha));
				}


				void main() {
					vec3 viewDir = normalize(v_viewPos - v_fragPos);
					vec3 lightDir = normalize(v_lightPos - v_fragPos);
					
					vec2 uv = v_uv;
					
					// For the bumpy surface normal, sample our normal map.
					// This uses the standard surface UV coordinates, because the texture should appear to be on the surface.
					vec3 surfaceNormal = normalize(texture2D(u_normalTex, v_uv).rgb * 2.0 - 1.0);
					
					// Refract view ray through bumpy glass
					float indexOfRefraction = 1.4;
					vec3 refractedViewDir = normalize(-refract(-viewDir, surfaceNormal, 1.0/indexOfRefraction));
					
					// Offset UV for parallax effect (simple, but works well for a consistent depth)
					// Note we can swap "refractedViewDir" for "viewDir" to lose the refraction effect
					float depth = 0.25;
					vec2 parallaxOffset = refractedViewDir.xy * depth / refractedViewDir.z;
					uv = uv - parallaxOffset;
					
					// Inner cube color uses parallax shifted UV
					// Also create an "empty border" around texture
					vec3 baseColor = vec3(0.067, 0.075, 0.094);
					if (uv.x >= 0.1 && uv.x <= 0.9 && uv.y >= 0.1 && uv.y <= 0.9) {
						baseColor = texture2D(u_colorTex, uv).rgb;
					}
					
					// No bump map for the "inner object", so the flat normal is simply +Z.
					// We could sample a normal map instead here...
					vec3 flatNormal = vec3(0.0, 0.0, 1.0);
					float diffuse = max(dot(lightDir, flatNormal), 0.0) * 0.75 + 0.25;
					baseColor = diffuse * baseColor;
					
					// Add Phong specular reflection on surface
					float shininess = 120.0;
					vec3 lightColor = vec3(0.9, 0.9, 0.9);
					vec3 black = vec3(0.0, 0.0, 0.0);
					vec3 white = vec3(1.0, 1.0, 1.0);
					vec3 specularValue = phongContribForLight(black, white, shininess, v_fragPos, surfaceNormal, v_viewPos, v_lightPos, lightColor);
					
					// Background reflection on glass at grazing angles
					float fresnel = 1.0 - max(dot(viewDir, surfaceNormal), 0.0);
					vec3 envColor = vec3(0.134, 0.150, 0.188);
					vec3 reflectionColor = fresnel * fresnel * envColor;
					
					gl_FragColor = vec4(baseColor + specularValue + reflectionColor, 1.0);
				}
			`
		});
	}
});


// The floor material is slightly different than the cube, as an additional alpha map texture is provided.
// The alpha map is used to draw opaque pixels on the surface of the material (without parallax).
// As such, this is a unique shader, though much is shared with the cube shader.
AFRAME.registerComponent('glass-floor', {
  schema: {},
  init() {
		const mesh = this.el.getObject3D('mesh');
		mesh.geometry.computeTangents();
		mesh.material = this.generateMaterial();
	},
	generateMaterial() {
		const baseColorTex = new THREE.TextureLoader().load('//repo.bfw.wiki/bfwrepo/images/cube/granite_color.jpg');
		baseColorTex.wrapS = THREE.RepeatWrapping;
		baseColorTex.wrapT = THREE.RepeatWrapping;
		const surfaceAlphaTex = new THREE.TextureLoader().load('//repo.bfw.wiki/bfwrepo/images/cube/tiles_alpha_map.png');
		surfaceAlphaTex.wrapS = THREE.RepeatWrapping;
		surfaceAlphaTex.wrapT = THREE.RepeatWrapping;
		const surfaceNormalTex = new THREE.TextureLoader().load('//repo.bfw.wiki/bfwrepo/images/cube/tiles_normal_map.jpg');
		surfaceNormalTex.wrapS = THREE.RepeatWrapping;
		surfaceNormalTex.wrapT = THREE.RepeatWrapping;
		return new THREE.ShaderMaterial({
			uniforms: {
				u_baseColorTex: { type: 't', value: baseColorTex },
				u_surfaceAlphaTex: { type: 't', value: surfaceAlphaTex },
				u_surfaceNormalTex: { type: 't', value: surfaceNormalTex }
			},
			vertexShader: `
				// THREE doesn't seem to add the "tangent" attribute automatically when we compute the t.........完整代码请登录后点击上方下载按钮下载查看

网友评论0