Shader code beginnings
This commit is contained in:
parent
1f873f7d87
commit
5b8b8fa057
@ -127,6 +127,25 @@ export class Matrix4x4 {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static fromTRS(t: Vector3Object, r: QuaternionObject, s: Vector3Object): Matrix4x4 {
|
||||||
|
const xx = r.x * r.x;
|
||||||
|
const xy = r.x * r.y;
|
||||||
|
const xz = r.x * r.z;
|
||||||
|
const xw = r.x * r.w;
|
||||||
|
const yy = r.y * r.y;
|
||||||
|
const yz = r.y * r.z;
|
||||||
|
const yw = r.y * r.w;
|
||||||
|
const zz = r.z * r.z;
|
||||||
|
const zw = r.z * r.w;
|
||||||
|
|
||||||
|
return new Matrix4x4(
|
||||||
|
s.x * (1 - 2 * (yy + zz)), s.x * 2 * (xy + zw), s.x * 2 * (xz - yw), 0,
|
||||||
|
s.y * 2 * (xy - zw), s.y * (1 - 2 * (xx + zz)), s.y * 2 * (yz + xw), 0,
|
||||||
|
s.z * 2 * (xz + yw), s.z * 2 * (yz - xw), s.z * (1 - 2 * (xx + yy)), 0,
|
||||||
|
t.x, t.y, t.z, 1,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
setObject(object: Matrix4x4Object): Matrix4x4 {
|
setObject(object: Matrix4x4Object): Matrix4x4 {
|
||||||
this.ix = object.ix;
|
this.ix = object.ix;
|
||||||
this.iy = object.iy;
|
this.iy = object.iy;
|
||||||
@ -236,6 +255,61 @@ export class Matrix4x4 {
|
|||||||
this.tw = 1;
|
this.tw = 1;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setTRS(t: Vector3Object, r: QuaternionObject, s: Vector3Object): Matrix4x4 {
|
||||||
|
const xx = r.x * r.x;
|
||||||
|
const xy = r.x * r.y;
|
||||||
|
const xz = r.x * r.z;
|
||||||
|
const xw = r.x * r.w;
|
||||||
|
const yy = r.y * r.y;
|
||||||
|
const yz = r.y * r.z;
|
||||||
|
const yw = r.y * r.w;
|
||||||
|
const zz = r.z * r.z;
|
||||||
|
const zw = r.z * r.w;
|
||||||
|
|
||||||
|
this.ix = s.x * (1 - 2 * (yy + zz));
|
||||||
|
this.iy = s.x * 2 * (xy + zw);
|
||||||
|
this.iz = s.x * 2 * (xz - yw);
|
||||||
|
this.iw = 0;
|
||||||
|
this.jx = s.y * 2 * (xy - zw);
|
||||||
|
this.jy = s.y * (1 - 2 * (xx + zz));
|
||||||
|
this.jz = s.y * 2 * (yz + xw);
|
||||||
|
this.jw = 0;
|
||||||
|
this.kx = s.z * 2 * (xz + yw);
|
||||||
|
this.ky = s.z * 2 * (yz - xw);
|
||||||
|
this.kz = s.z * (1 - 2 * (xx + yy));
|
||||||
|
this.kw = 0;
|
||||||
|
this.tx = t.x;
|
||||||
|
this.ty = t.y;
|
||||||
|
this.tz = t.z;
|
||||||
|
this.tw = 1;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
add(m: Matrix4x4): Matrix4x4 {
|
||||||
|
throw new Error("TODO");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub(m: Matrix4x4): Matrix4x4 {
|
||||||
|
throw new Error("TODO");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
mulScalar(k: number): Matrix4x4 {
|
||||||
|
throw new Error("TODO");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
mulMatrix(m: Matrix4x4): Matrix4x4 {
|
||||||
|
throw new Error("TODO");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
premulMatrix(m: Matrix4x4): Matrix4x4 {
|
||||||
|
throw new Error("TODO");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Object.defineProperty(Matrix4x4.prototype, "type", { value: "Matrix4x4" });
|
Object.defineProperty(Matrix4x4.prototype, "type", { value: "Matrix4x4" });
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
* obtain one at http://mozilla.org/MPL/2.0/.
|
* obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Camera, Mesh, Quaternion, QuaternionObject, Vector3, Vector3Object } from ".";
|
import { Camera, Matrix4x4, Mesh, Quaternion, QuaternionObject, Vector3, Vector3Object } from ".";
|
||||||
import { Material } from "../resources";
|
import { Material } from "../resources";
|
||||||
|
|
||||||
export interface NodeProps {
|
export interface NodeProps {
|
||||||
@ -44,6 +44,9 @@ export class Node {
|
|||||||
/** backreference */
|
/** backreference */
|
||||||
_parent: Node | null;
|
_parent: Node | null;
|
||||||
|
|
||||||
|
_localMatrix: Matrix4x4;
|
||||||
|
_worldMatrix: Matrix4x4;
|
||||||
|
|
||||||
constructor({
|
constructor({
|
||||||
name = "",
|
name = "",
|
||||||
translation,
|
translation,
|
||||||
@ -68,6 +71,9 @@ export class Node {
|
|||||||
|
|
||||||
this._parent = null;
|
this._parent = null;
|
||||||
|
|
||||||
|
this._localMatrix = Matrix4x4.fromTRS(this._translation, this._rotation, this._scale);
|
||||||
|
this._worldMatrix = Matrix4x4.fromObject(this._localMatrix);
|
||||||
|
|
||||||
if (this._camera !== null) {
|
if (this._camera !== null) {
|
||||||
this._camera._node = this;
|
this._camera._node = this;
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
* obtain one at http://mozilla.org/MPL/2.0/.
|
* obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { Camera, Scene } from "./data";
|
||||||
import { IndexBuffer, IndexBufferProps, Material, MaterialProps, Texture2D, Texture2DProps, VertexBuffer, VertexBufferProps } from "./resources";
|
import { IndexBuffer, IndexBufferProps, Material, MaterialProps, Texture2D, Texture2DProps, VertexBuffer, VertexBufferProps } from "./resources";
|
||||||
|
|
||||||
export class Renderer {
|
export class Renderer {
|
||||||
@ -20,6 +21,8 @@ export class Renderer {
|
|||||||
/** 1×1 rgba8unorm texture of [128, 128, 128, 255] */
|
/** 1×1 rgba8unorm texture of [128, 128, 128, 255] */
|
||||||
_textureNormal: Texture2D;
|
_textureNormal: Texture2D;
|
||||||
|
|
||||||
|
_depthBuffer: Texture2D;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This constructor is intended primarily for internal use. Consider using
|
* This constructor is intended primarily for internal use. Consider using
|
||||||
* `Renderer.createIndexBuffer` instead.
|
* `Renderer.createIndexBuffer` instead.
|
||||||
@ -36,6 +39,7 @@ export class Renderer {
|
|||||||
this._format = format;
|
this._format = format;
|
||||||
|
|
||||||
this._textureWhite = new Texture2D(this, {
|
this._textureWhite = new Texture2D(this, {
|
||||||
|
name: "White",
|
||||||
width: 1,
|
width: 1,
|
||||||
height: 1,
|
height: 1,
|
||||||
format: "linear",
|
format: "linear",
|
||||||
@ -43,6 +47,7 @@ export class Renderer {
|
|||||||
this._textureWhite.writeFull(new Uint8Array([255, 255, 255, 255]));
|
this._textureWhite.writeFull(new Uint8Array([255, 255, 255, 255]));
|
||||||
|
|
||||||
this._textureBlack = new Texture2D(this, {
|
this._textureBlack = new Texture2D(this, {
|
||||||
|
name: "Black",
|
||||||
width: 1,
|
width: 1,
|
||||||
height: 1,
|
height: 1,
|
||||||
format: "linear",
|
format: "linear",
|
||||||
@ -50,11 +55,20 @@ export class Renderer {
|
|||||||
this._textureBlack.writeFull(new Uint8Array([0, 0, 0, 255]));
|
this._textureBlack.writeFull(new Uint8Array([0, 0, 0, 255]));
|
||||||
|
|
||||||
this._textureNormal = new Texture2D(this, {
|
this._textureNormal = new Texture2D(this, {
|
||||||
|
name: "Normal",
|
||||||
width: 1,
|
width: 1,
|
||||||
height: 1,
|
height: 1,
|
||||||
format: "linear",
|
format: "linear",
|
||||||
});
|
});
|
||||||
this._textureNormal.writeFull(new Uint8Array([128, 128, 128, 255]));
|
this._textureNormal.writeFull(new Uint8Array([128, 128, 128, 255]));
|
||||||
|
|
||||||
|
const framebufferTexture = this._context.getCurrentTexture();
|
||||||
|
this._depthBuffer = new Texture2D(this, {
|
||||||
|
name: "Depth Buffer",
|
||||||
|
width: framebufferTexture.width,
|
||||||
|
height: framebufferTexture.height,
|
||||||
|
format: "depth",
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static async init(canvas: HTMLCanvasElement) {
|
static async init(canvas: HTMLCanvasElement) {
|
||||||
@ -90,6 +104,7 @@ export class Renderer {
|
|||||||
this._textureWhite.dispose();
|
this._textureWhite.dispose();
|
||||||
this._textureBlack.dispose();
|
this._textureBlack.dispose();
|
||||||
this._textureNormal.dispose();
|
this._textureNormal.dispose();
|
||||||
|
this._depthBuffer.dispose();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,4 +123,36 @@ export class Renderer {
|
|||||||
createVertexBuffer(props: VertexBufferProps): VertexBuffer {
|
createVertexBuffer(props: VertexBufferProps): VertexBuffer {
|
||||||
return new VertexBuffer(this, props);
|
return new VertexBuffer(this, props);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
render(scene: Scene, camera: Camera): Renderer {
|
||||||
|
const { width, height } = this._context.getCurrentTexture();
|
||||||
|
if (this._depthBuffer.width !== width || this._depthBuffer.height !== height) {
|
||||||
|
this._depthBuffer.resizeDiscard({
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const encoder = this._device.createCommandEncoder();
|
||||||
|
|
||||||
|
const pass = encoder.beginRenderPass({
|
||||||
|
colorAttachments: [{
|
||||||
|
view: this._context.getCurrentTexture().createView(),
|
||||||
|
loadOp: "clear",
|
||||||
|
storeOp: "store",
|
||||||
|
}],
|
||||||
|
depthStencilAttachment: {
|
||||||
|
view: this._depthBuffer._textureView,
|
||||||
|
depthClearValue: 0,
|
||||||
|
depthLoadOp: "clear",
|
||||||
|
depthStoreOp: "store",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
pass.end();
|
||||||
|
|
||||||
|
const commandBuffer = encoder.finish();
|
||||||
|
this._device.queue.submit([commandBuffer]);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,17 +15,18 @@ export interface MaterialProps {
|
|||||||
|
|
||||||
baseColor?: ColorObject;
|
baseColor?: ColorObject;
|
||||||
partialCoverage?: number;
|
partialCoverage?: number;
|
||||||
occlusionTextureStrength?: number;
|
|
||||||
metallic?: number;
|
|
||||||
roughness?: number;
|
|
||||||
normalScale?: number;
|
|
||||||
emissive?: ColorObject;
|
|
||||||
transmission?: ColorObject;
|
transmission?: ColorObject;
|
||||||
collimation?: number;
|
collimation?: number;
|
||||||
|
occlusionTextureStrength?: number;
|
||||||
|
roughness?: number;
|
||||||
|
metallic?: number;
|
||||||
|
normalScale?: number;
|
||||||
|
emissive?: ColorObject;
|
||||||
ior?: number;
|
ior?: number;
|
||||||
|
|
||||||
baseColorPartialCoverageTexture?: Texture2D | null;
|
baseColorPartialCoverageTexture?: Texture2D | null;
|
||||||
occlusionMetallicRoughnessTexture?: Texture2D | null;
|
occlusionTexture?: Texture2D | null;
|
||||||
|
metallicRoughnessTexture?: Texture2D | null;
|
||||||
normalTexture?: Texture2D | null;
|
normalTexture?: Texture2D | null;
|
||||||
emissiveTexture?: Texture2D | null;
|
emissiveTexture?: Texture2D | null;
|
||||||
transmissionCollimationTexture?: Texture2D | null;
|
transmissionCollimationTexture?: Texture2D | null;
|
||||||
@ -53,7 +54,8 @@ export class Material {
|
|||||||
_ior: number;
|
_ior: number;
|
||||||
|
|
||||||
_baseColorPartialCoverageTexture: Texture2D | null;
|
_baseColorPartialCoverageTexture: Texture2D | null;
|
||||||
_occlusionMetallicRoughnessTexture: Texture2D | null;
|
_occlusionTexture: Texture2D | null;
|
||||||
|
_metallicRoughnessTexture: Texture2D | null;
|
||||||
_normalTexture: Texture2D | null;
|
_normalTexture: Texture2D | null;
|
||||||
_emissiveTexture: Texture2D | null;
|
_emissiveTexture: Texture2D | null;
|
||||||
_transmissionCollimationTexture: Texture2D | null;
|
_transmissionCollimationTexture: Texture2D | null;
|
||||||
@ -74,7 +76,8 @@ export class Material {
|
|||||||
collimation = 1,
|
collimation = 1,
|
||||||
ior = 1.45,
|
ior = 1.45,
|
||||||
baseColorPartialCoverageTexture = null,
|
baseColorPartialCoverageTexture = null,
|
||||||
occlusionMetallicRoughnessTexture = null,
|
occlusionTexture = null,
|
||||||
|
metallicRoughnessTexture = null,
|
||||||
normalTexture = null,
|
normalTexture = null,
|
||||||
emissiveTexture = null,
|
emissiveTexture = null,
|
||||||
transmissionCollimationTexture = null,
|
transmissionCollimationTexture = null,
|
||||||
@ -97,7 +100,8 @@ export class Material {
|
|||||||
this._ior = ior;
|
this._ior = ior;
|
||||||
|
|
||||||
this._baseColorPartialCoverageTexture = baseColorPartialCoverageTexture;
|
this._baseColorPartialCoverageTexture = baseColorPartialCoverageTexture;
|
||||||
this._occlusionMetallicRoughnessTexture = occlusionMetallicRoughnessTexture;
|
this._occlusionTexture = occlusionTexture;
|
||||||
|
this._metallicRoughnessTexture = metallicRoughnessTexture;
|
||||||
this._normalTexture = normalTexture;
|
this._normalTexture = normalTexture;
|
||||||
this._emissiveTexture = emissiveTexture;
|
this._emissiveTexture = emissiveTexture;
|
||||||
this._transmissionCollimationTexture = transmissionCollimationTexture;
|
this._transmissionCollimationTexture = transmissionCollimationTexture;
|
||||||
|
136
src/shader.ts
Normal file
136
src/shader.ts
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
export interface ShaderFlags {
|
||||||
|
texCoord: boolean;
|
||||||
|
lightTexCoord: boolean;
|
||||||
|
normal: boolean;
|
||||||
|
tangent: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createShaderCode({
|
||||||
|
texCoord,
|
||||||
|
lightTexCoord,
|
||||||
|
normal,
|
||||||
|
tangent,
|
||||||
|
}: ShaderFlags): string {
|
||||||
|
let vertexLocation = 0;
|
||||||
|
let varyingLocation = 0;
|
||||||
|
|
||||||
|
return `
|
||||||
|
struct Vertex {
|
||||||
|
@location(${vertexLocation++}) positionOS: vec3<f32>,
|
||||||
|
${texCoord ? `@location(${vertexLocation++}) texCoord: vec2<f32>,` : ""}
|
||||||
|
${lightTexCoord ? `@location(${vertexLocation++}) lightTexCoord: vec2<f32>,` : ""}
|
||||||
|
${normal ? `@location(${vertexLocation++}) normalOS: vec3<f32>,` : ""}
|
||||||
|
${normal && tangent ? `@location(${vertexLocation++}) tangentOS: vec4<f32>,` : ""}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Varyings {
|
||||||
|
@builtin(position) positionCS: vec4<f32>,
|
||||||
|
@location(${varyingLocation++}) positionVS: vec4<f32>,
|
||||||
|
${texCoord ? `@location(${varyingLocation++}) texCoord: vec2<f32>,` : ""}
|
||||||
|
${lightTexCoord ? `@location(${varyingLocation++}) lightTexCoord: vec2<f32>,` : ""}
|
||||||
|
${normal ? `@location(${varyingLocation++}) normalVS: vec3<f32>,` : ""}
|
||||||
|
${normal && tangent ? `@location(${varyingLocation++}) tangentVS: vec3<f32>,` : ""}
|
||||||
|
${normal && tangent ? `@location(${varyingLocation++}) bitangentVS: vec3<f32>,` : ""}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct PointLight {
|
||||||
|
positionWS: vec3<f32>,
|
||||||
|
color: vec3<f32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct DirectionalLight {
|
||||||
|
directionWS: vec3<f32>,
|
||||||
|
color: vec3<f32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct GlobalUniforms {
|
||||||
|
matrixWStoVS: mat4x4<f32>,
|
||||||
|
matrixVStoCS: mat4x4<f32>,
|
||||||
|
ambientLight: vec3<f32>,
|
||||||
|
pointLightCount: u32,
|
||||||
|
directionalLightCount: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MaterialUniforms {
|
||||||
|
baseColor: vec3<f32>,
|
||||||
|
partialCoverage: f32,
|
||||||
|
transmission: vec3<f32>,
|
||||||
|
collimation: f32,
|
||||||
|
occlusionTextureStrength: f32,
|
||||||
|
roughness: f32,
|
||||||
|
metallic: f32,
|
||||||
|
normalScale: f32,
|
||||||
|
emissive: vec3<f32>,
|
||||||
|
ior: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ObjectUniforms {
|
||||||
|
matrixOStoWS: mat4x4<f32>,
|
||||||
|
matrixOStoWSNormal: mat4x4<f32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
@group(0) @binding(0) var<uniform> _Global: GlobalUniforms;
|
||||||
|
@group(1) @binding(0) var<uniform> _Material: MaterialUniforms;
|
||||||
|
@group(2) @binding(0) var<uniform> _Object: ObjectUniforms;
|
||||||
|
|
||||||
|
@group(0) @binding(1) var<storage> _PointLights: array<PointLight>;
|
||||||
|
@group(0) @binding(2) var<storage> _DirectionalLights: array<DirectionalLight>;
|
||||||
|
|
||||||
|
@group(1) @binding(1) var _Sampler: sampler;
|
||||||
|
@group(1) @binding(2) var _BaseColorPartialCoverageTexture: texture_2d<f32>;
|
||||||
|
@group(1) @binding(3) var _OcclusionTexture: texture_2d<f32>;
|
||||||
|
@group(1) @binding(4) var _RoughnessMetallicTexture: texture_2d<f32>;
|
||||||
|
@group(1) @binding(5) var _NormalTexture: texture_2d<f32>;
|
||||||
|
@group(1) @binding(6) var _EmissiveTexture: texture_2d<f32>;
|
||||||
|
@group(1) @binding(7) var _TransmissionCollimationTexture: texture_2d<f32>;
|
||||||
|
|
||||||
|
@vertex
|
||||||
|
fn vert(vertex: Vertex) -> Varyings {
|
||||||
|
var output: Varyings;
|
||||||
|
let positionWS = (_Object.matrixOStoWS * vec4(vertex.positionOS, 1.0)).xyz;
|
||||||
|
let positionVS = (_Global.matrixWStoVS * vec4(positionWS, 1.0)).xyz;
|
||||||
|
let positionCS = _Global.matrixVStoCS * vec4(positionVS, 1.0);
|
||||||
|
output.positionCS = positionCS;
|
||||||
|
output.positionVS = positionVS;
|
||||||
|
${normal ? `
|
||||||
|
let normalWS = normalize((_Object.matrixOStoWSNormal * vec4(vertex.normalOS, 0.0)).xyz);
|
||||||
|
let normalVS = normalize((_Global.matrixWStoVS * vec4(normalWS, 0.0)).xyz);
|
||||||
|
output.normalVS = normalVS;
|
||||||
|
${tangent ? `
|
||||||
|
let tangentWS = normalize((_Object.matrixOStoWS * vec4(vertex.tangentOS.xyz, 0.0)).xyz);
|
||||||
|
let tangentVS = normalize((_Global.matrixWStoVS * vec4(tangentWS, 0.0)).xyz);
|
||||||
|
let bitangentVS = vertex.tangentOS.w * normalize(cross(normalVS, tangentVS));
|
||||||
|
output.tangentVS = tangentVS;
|
||||||
|
output.bitangentVS = bitangentVS;
|
||||||
|
` : ""}
|
||||||
|
` : ""}
|
||||||
|
${texCoord ? "output.texCoord = vertex.texCoord;" : ""}
|
||||||
|
${lightTexCoord ? "output.lightTexCoord = vertex.lightTexCoord;" : ""}
|
||||||
|
}
|
||||||
|
|
||||||
|
@fragment
|
||||||
|
fn frag(fragment: Varyings) -> @location(0) vec2<f32> {
|
||||||
|
var baseColor = _Material.baseColor;
|
||||||
|
var partialCoverage = _Material.partialCoverage;
|
||||||
|
var occlusion = 1.0;
|
||||||
|
var roughness = _Material.roughness;
|
||||||
|
var metallic = _Material.metallic;
|
||||||
|
var normalScale = _Material.normalScale;
|
||||||
|
var emissive = _Material.emissive;
|
||||||
|
var ior = _Material.ior;
|
||||||
|
${texCoord ? `
|
||||||
|
let baseColorPartialCoverageTexel = texture(_BaseColorPartialCoverageTexture, _Sampler, fragment.texCoord);
|
||||||
|
baseColor *= baseColorPartialCoverageTexel.rgb;
|
||||||
|
partialCoverage *= baseColorPartialCoverageTexel.a;
|
||||||
|
let roughnessMetallicTexel = texture(_RoughnessMetallic, _Sampler, fragment.texCoord);
|
||||||
|
roughness *= roughnessMetallicTexel.g;
|
||||||
|
metallic *= roughnessMetallicTexel.b;
|
||||||
|
let emissiveTexel = texture(_EmissiveTexture, _Sampler, fragment.texCoord);
|
||||||
|
emissive *= emissiveTexel.rgb;
|
||||||
|
` : ""}
|
||||||
|
${lightTexCoord ? `
|
||||||
|
let occlusionTexel = texture(_OcclusionTexture, _Sampler, fragment.lightTexCoord);
|
||||||
|
occlusion += _Material.occlusionTextureStrength * (occlusionTexel.r - 1.0);
|
||||||
|
` : ""}
|
||||||
|
}`;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user