Compare commits

...
Sign in to create a new pull request.

4 commits

Author SHA1 Message Date
Vitaly Turovsky
60a39bbaf5 fix depth 2025-04-25 04:29:26 +03:00
Vitaly Turovsky
d4cc305baa sprm 2025-04-25 04:16:45 +03:00
Vitaly Turovsky
777b2c41e7 Merge branch 'next' into threejs-shaders 2025-04-25 04:16:38 +03:00
Vitaly Turovsky
ad8c57de82 init 2025-04-24 05:47:58 +03:00
2 changed files with 151 additions and 13 deletions

View file

@ -0,0 +1,94 @@
import { ShaderChunk } from 'three'
// Original simple shader for non-animated blocks
export const BLOCK_VERTEX_SHADER = `
#include <common>
${ShaderChunk.logdepthbuf_pars_vertex}
attribute vec3 color;
varying vec2 vUv;
varying vec3 vColor;
void main() {
vUv = uv;
vColor = color;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
${ShaderChunk.logdepthbuf_vertex}
}
`
export const BLOCK_FRAGMENT_SHADER = `
#include <common>
${ShaderChunk.logdepthbuf_pars_fragment}
uniform sampler2D map;
varying vec2 vUv;
varying vec3 vColor;
void main() {
vec4 texColor = texture2D(map, vUv);
if (texColor.a < 0.1) discard;
gl_FragColor = vec4(vColor * texColor.rgb, texColor.a);
${ShaderChunk.logdepthbuf_fragment}
}
`
// New shader for animated blocks
export const ANIMATED_BLOCK_VERTEX_SHADER = `
#include <common>
${ShaderChunk.logdepthbuf_pars_vertex}
uniform float animationFrameHeight;
uniform float animationFrameIndex;
uniform float animationInterpolationFrameIndex;
uniform float animationInterpolation;
attribute vec3 color;
varying vec2 vUv;
varying vec3 vColor;
varying float vAnimationInterpolation;
void main() {
vUv = uv;
vColor = color;
vAnimationInterpolation = animationInterpolation;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
${ShaderChunk.logdepthbuf_vertex}
}
`
export const ANIMATED_BLOCK_FRAGMENT_SHADER = `
#include <common>
${ShaderChunk.logdepthbuf_pars_fragment}
uniform sampler2D map;
uniform float animationFrameHeight;
uniform float animationFrameIndex;
uniform float animationInterpolationFrameIndex;
varying vec2 vUv;
varying vec3 vColor;
varying float vAnimationInterpolation;
void main() {
// Calculate UV coordinates for current frame
vec2 currentFrameUv = vec2(vUv.x, animationFrameHeight * (vUv.y + animationFrameIndex));
vec4 currentFrame = texture2D(map, currentFrameUv);
// If interpolation is enabled, calculate UV for next frame and mix
if (vAnimationInterpolation > 0.0) {
vec2 nextFrameUv = vec2(vUv.x, animationFrameHeight * (vUv.y + animationInterpolationFrameIndex));
vec4 nextFrame = texture2D(map, nextFrameUv);
currentFrame = mix(currentFrame, nextFrame, vAnimationInterpolation);
}
if (currentFrame.a < 0.1) discard;
gl_FragColor = vec4(vColor * currentFrame.rgb, currentFrame.a);
${ShaderChunk.logdepthbuf_fragment}
}
`

View file

@ -25,10 +25,49 @@ import { Entities } from './entities'
import { ThreeJsSound } from './threeJsSound'
import { CameraShake } from './cameraShake'
import { ThreeJsMedia } from './threeJsMedia'
import { BLOCK_VERTEX_SHADER, BLOCK_FRAGMENT_SHADER, ANIMATED_BLOCK_VERTEX_SHADER, ANIMATED_BLOCK_FRAGMENT_SHADER } from './shadersThree'
import { Fountain } from './threeJsParticles'
type SectionKey = string
class CustomBlockMaterial extends THREE.ShaderMaterial {
constructor () {
super({
uniforms: {
map: { value: null }
},
vertexShader: BLOCK_VERTEX_SHADER,
fragmentShader: BLOCK_FRAGMENT_SHADER,
transparent: true,
alphaTest: 0.1,
depthWrite: true,
depthTest: true,
side: THREE.FrontSide
})
}
}
class AnimatedBlockMaterial extends THREE.ShaderMaterial {
constructor () {
super({
uniforms: {
map: { value: null },
animationFrameHeight: { value: 1 },
animationFrameIndex: { value: 0 },
animationInterpolationFrameIndex: { value: 0 },
animationInterpolation: { value: 0 }
},
vertexShader: ANIMATED_BLOCK_VERTEX_SHADER,
fragmentShader: ANIMATED_BLOCK_FRAGMENT_SHADER,
transparent: true,
alphaTest: 0.1,
depthWrite: true,
depthTest: true,
side: THREE.FrontSide
})
}
}
export class WorldRendererThree extends WorldRendererCommon {
outputFormat = 'threeJs' as const
sectionObjects: Record<string, THREE.Object3D & { foutain?: boolean }> = {}
@ -36,14 +75,15 @@ export class WorldRendererThree extends WorldRendererCommon {
signsCache = new Map<string, any>()
starField: StarField
cameraSectionPos: Vec3 = new Vec3(0, 0, 0)
holdingBlock: HoldingBlock
holdingBlockLeft: HoldingBlock
holdingBlock: HoldingBlock | undefined
holdingBlockLeft: HoldingBlock | undefined
scene = new THREE.Scene()
ambientLight = new THREE.AmbientLight(0xcc_cc_cc)
directionalLight = new THREE.DirectionalLight(0xff_ff_ff, 0.5)
entities = new Entities(this)
cameraObjectOverride?: THREE.Object3D // for xr
material = new THREE.MeshLambertMaterial({ vertexColors: true, transparent: true, alphaTest: 0.1 })
material = new CustomBlockMaterial()
animatedMaterial = new AnimatedBlockMaterial()
itemsTexture: THREE.Texture
cursorBlock = new CursorBlock(this)
onRender: Array<() => void> = []
@ -168,23 +208,23 @@ export class WorldRendererThree extends WorldRendererCommon {
changeHandSwingingState (isAnimationPlaying: boolean, isLeft = false) {
const holdingBlock = isLeft ? this.holdingBlockLeft : this.holdingBlock
if (isAnimationPlaying) {
holdingBlock.startSwing()
holdingBlock?.startSwing()
} else {
holdingBlock.stopSwing()
holdingBlock?.stopSwing()
}
}
async updateAssetsData (): Promise<void> {
const resources = this.resourcesManager.currentResources!
const oldTexture = this.material.map
const oldTexture = this.material.uniforms.map.value
const oldItemsTexture = this.itemsTexture
const texture = await new THREE.TextureLoader().loadAsync(resources.blocksAtlasParser.latestImage)
texture.magFilter = THREE.NearestFilter
texture.minFilter = THREE.NearestFilter
texture.flipY = false
this.material.map = texture
this.material.uniforms.map.value = texture
const itemsTexture = await new THREE.TextureLoader().loadAsync(resources.itemsAtlasParser.latestImage)
itemsTexture.magFilter = THREE.NearestFilter
@ -208,10 +248,14 @@ export class WorldRendererThree extends WorldRendererCommon {
}
onAllTexturesLoaded () {
this.holdingBlock.ready = true
this.holdingBlock.updateItem()
this.holdingBlockLeft.ready = true
this.holdingBlockLeft.updateItem()
if (this.holdingBlock) {
this.holdingBlock.ready = true
this.holdingBlock.updateItem()
}
if (this.holdingBlockLeft) {
this.holdingBlockLeft.ready = true
this.holdingBlockLeft.updateItem()
}
}
changeBackgroundColor (color: [number, number, number]): void {
@ -464,8 +508,8 @@ export class WorldRendererThree extends WorldRendererCommon {
this.renderer.render(this.scene, cam)
if (this.displayOptions.inWorldRenderingConfig.showHand/* && !this.freeFlyMode */) {
this.holdingBlock.render(this.camera, this.renderer, this.ambientLight, this.directionalLight)
this.holdingBlockLeft.render(this.camera, this.renderer, this.ambientLight, this.directionalLight)
this.holdingBlock?.render(this.camera, this.renderer, this.ambientLight, this.directionalLight)
this.holdingBlockLeft?.render(this.camera, this.renderer, this.ambientLight, this.directionalLight)
}
for (const fountain of this.fountains) {