Skip to content

Commit

Permalink
Merge pull request #9964 from CesiumGS/color-vec3-custom-shaders
Browse files Browse the repository at this point in the history
Handle vec3 colors correctly in custom shaders
  • Loading branch information
lilleyse authored Dec 6, 2021
2 parents 1b4810b + d311ce2 commit 5c4f9af
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 42 deletions.
3 changes: 2 additions & 1 deletion Apps/Sandcastle/gallery/Custom Shaders Models.html
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,8 @@
// of the wave, but at a different speed.
// Coefficients were chosen arbitrarily
" vec2 uv = fsInput.attributes.positionMC.xy;",
" material.diffuse = vec3(0.2, 0.3, 0.4) + vec3(0.2, 0.3, 0.4) * sin(2.0 * czm_pi * vec3(3.0, 2.0, 1.0) * uv.x - 3.0 * u_time);",
" material.diffuse = 0.2 * fsInput.attributes.color_0.rgb;",
" material.diffuse += vec3(0.2, 0.3, 0.4) + vec3(0.2, 0.3, 0.4) * sin(2.0 * czm_pi * vec3(3.0, 2.0, 1.0) * uv.x - 3.0 * u_time);",
"}",
].join("\n"),
});
Expand Down
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

- Fixed handling of vec3 vertex colors in `ModelExperimental`. [#9955](https://github.com/CesiumGS/cesium/pull/9955)
- Fixed handling of Draco quantized vec3 vertex colors in `ModelExperimental`. [#9957](https://github.com/CesiumGS/cesium/pull/9957)
- Fixed handling of vec3 vertex colors in `CustomShaderPipelineStage`. [#9964](https://github.com/CesiumGS/cesium/pull/9964)

### 1.88 - 2021-12-01

Expand Down
59 changes: 20 additions & 39 deletions Source/Scene/ModelExperimental/CustomShaderPipelineStage.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,9 @@ import ShaderDestination from "../../Renderer/ShaderDestination.js";
import Pass from "../../Renderer/Pass.js";
import CustomShaderStageVS from "../../Shaders/ModelExperimental/CustomShaderStageVS.js";
import CustomShaderStageFS from "../../Shaders/ModelExperimental/CustomShaderStageFS.js";
import VertexAttributeSemantic from "../VertexAttributeSemantic.js";
import AttributeType from "../AttributeType.js";
import AlphaMode from "../AlphaMode.js";
import CustomShaderMode from "./CustomShaderMode.js";
import ModelExperimentalUtility from "./ModelExperimentalUtility.js";

/**
* The custom shader pipeline stage takes GLSL callbacks from the
Expand Down Expand Up @@ -154,47 +153,25 @@ CustomShaderPipelineStage.process = function (
);
};

function getAttributeNames(attributes) {
function getAttributesByName(attributes) {
var names = {};
for (var i = 0; i < attributes.length; i++) {
var attribute = attributes[i];
var semantic = attribute.semantic;
var setIndex = attribute.setIndex;

var variableName;
if (defined(semantic)) {
variableName = VertexAttributeSemantic.getVariableName(
semantic,
setIndex
);
} else {
// Handle user defined vertex attributes. They must begin with an underscore
// For example, "_TEMPERATURE" will be converted to "temperature".
variableName = attribute.name.substring(1).toLowerCase();
}
var attributeInfo = ModelExperimentalUtility.getAttributeInfo(attribute);

names[variableName] = attribute;
names[attributeInfo.variableName] = attributeInfo;
}
return names;
}

function generateAttributeField(name, attribute) {
var attributeType = attribute.type;
var glslType = AttributeType.getGlslType(attributeType);

// Fields for the Attribute struct. for example:
// ["vec3", "normal"];
return [glslType, name];
}

// GLSL types of standard attribute types when uniquely defined
var attributeTypeLUT = {
position: "vec3",
normal: "vec3",
tangent: "vec3",
bitangent: "vec3",
texCoord: "vec2",
color: "vec3",
color: "vec4",
joints: "ivec4",
weights: "vec4",
};
Expand Down Expand Up @@ -231,9 +208,13 @@ function inferAttributeDefaults(attributeName) {
};
}

function generateVertexShaderLines(customShader, namedAttributes, vertexLines) {
function generateVertexShaderLines(
customShader,
attributesByName,
vertexLines
) {
var categories = partitionAttributes(
namedAttributes,
attributesByName,
customShader.usedVariablesVertex.attributeSet,
false
);
Expand All @@ -246,8 +227,8 @@ function generateVertexShaderLines(customShader, namedAttributes, vertexLines) {
var initializationLines = [];
for (variableName in addToShader) {
if (addToShader.hasOwnProperty(variableName)) {
var attribute = addToShader[variableName];
var attributeField = generateAttributeField(variableName, attribute);
var attributeInfo = addToShader[variableName];
var attributeField = [attributeInfo.glslType, variableName];
attributeFields.push(attributeField);

// Initializing attribute structs are just a matter of copying the
Expand Down Expand Up @@ -326,11 +307,11 @@ function generatePositionBuiltins(customShader) {

function generateFragmentShaderLines(
customShader,
namedAttributes,
attributesByName,
fragmentLines
) {
var categories = partitionAttributes(
namedAttributes,
attributesByName,
customShader.usedVariablesFragment.attributeSet,
true
);
Expand All @@ -343,9 +324,9 @@ function generateFragmentShaderLines(
var initializationLines = [];
for (variableName in addToShader) {
if (addToShader.hasOwnProperty(variableName)) {
var attribute = addToShader[variableName];
var attributeInfo = addToShader[variableName];

var attributeField = generateAttributeField(variableName, attribute);
var attributeField = [attributeInfo.glslType, variableName];
attributeFields.push(attributeField);

// Initializing attribute structs are just a matter of copying the
Expand Down Expand Up @@ -484,13 +465,13 @@ function generateShaderLines(customShader, primitive) {

// Attempt to generate vertex and fragment shader lines before adding any
// code to the shader.
var namedAttributes = getAttributeNames(primitive.attributes);
var attributesByName = getAttributesByName(primitive.attributes);
if (defined(customShader.vertexShaderText)) {
generateVertexShaderLines(customShader, namedAttributes, vertexLines);
generateVertexShaderLines(customShader, attributesByName, vertexLines);
}

if (defined(customShader.fragmentShaderText)) {
generateFragmentShaderLines(customShader, namedAttributes, fragmentLines);
generateFragmentShaderLines(customShader, attributesByName, fragmentLines);
}

// positionWC must be computed in the vertex shader
Expand Down
104 changes: 102 additions & 2 deletions Specs/Scene/ModelExperimental/CustomShaderPipelineStageSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,25 @@ describe("Scene/ModelExperimental/CustomShaderPipelineStage", function () {
],
};

var primitiveWithColorAttributes = {
attributes: [
{
semantic: "POSITION",
type: AttributeType.VEC3,
},
{
semantic: "COLOR",
setIndex: 0,
type: AttributeType.VEC3,
},
{
semantic: "COLOR",
setIndex: 1,
type: AttributeType.VEC4,
},
],
};

var emptyVertexShader =
"void vertexMain(VertexInput vsInput, inout czm_modelVertexOutput vsOutput) {}";
var emptyFragmentShader =
Expand Down Expand Up @@ -227,7 +246,7 @@ describe("Scene/ModelExperimental/CustomShaderPipelineStage", function () {
"{",
" vec3 normalMC = vsInput.attributes.normalMC;",
" vec2 texCoord = vsInput.attributes.texCoord_0;",
" positionMC = vsInput.attributes.positionMC;",
" vsOutput.positionMC = vsInput.attributes.positionMC;",
"}",
].join("\n"),
fragmentShaderText: [
Expand Down Expand Up @@ -375,14 +394,95 @@ describe("Scene/ModelExperimental/CustomShaderPipelineStage", function () {
);
});

it("treats COLOR attributes as vec4", function () {
var shaderBuilder = new ShaderBuilder();
var model = {
customShader: new CustomShader({
varyings: {
v_color: VaryingType.FLOAT,
v_computedMatrix: VaryingType.MAT3,
},
vertexShaderText: [
"void vertexMain(VertexInput vsInput, inout czm_modelVertexOutput vsOutput)",
"{",
" vec4 color += vsInput.attributes.color_0 + vsInput.attributes.color_1;",
"}",
],
fragmentShaderText: [
"void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material)",
"{",
" vec4 color += fsInput.attributes.color_0 + fsInput.attributes.color_1;",
"}",
],
}),
};

var renderResources = {
shaderBuilder: shaderBuilder,
model: model,
lightingOptions: new ModelLightingOptions(),
alphaOptions: new ModelAlphaOptions(),
};

CustomShaderPipelineStage.process(
renderResources,
primitiveWithColorAttributes
);

ShaderBuilderTester.expectHasVertexStruct(
shaderBuilder,
CustomShaderPipelineStage.STRUCT_ID_ATTRIBUTES_VS,
CustomShaderPipelineStage.STRUCT_NAME_ATTRIBUTES,
[" vec4 color_0;", " vec4 color_1;"]
);
ShaderBuilderTester.expectHasFragmentStruct(
shaderBuilder,
CustomShaderPipelineStage.STRUCT_ID_ATTRIBUTES_FS,
CustomShaderPipelineStage.STRUCT_NAME_ATTRIBUTES,
[" vec4 color_0;", " vec4 color_1;"]
);

ShaderBuilderTester.expectHasVertexStruct(
shaderBuilder,
CustomShaderPipelineStage.STRUCT_ID_VERTEX_INPUT,
"VertexInput",
[" Attributes attributes;"]
);
ShaderBuilderTester.expectHasFragmentStruct(
shaderBuilder,
CustomShaderPipelineStage.STRUCT_ID_FRAGMENT_INPUT,
"FragmentInput",
[" Attributes attributes;"]
);

ShaderBuilderTester.expectHasVertexFunction(
shaderBuilder,
CustomShaderPipelineStage.FUNCTION_ID_INITIALIZE_INPUT_STRUCT_VS,
CustomShaderPipelineStage.FUNCTION_SIGNATURE_INITIALIZE_INPUT_STRUCT_VS,
[
" vsInput.attributes.color_0 = attributes.color_0;",
" vsInput.attributes.color_1 = attributes.color_1;",
]
);
ShaderBuilderTester.expectHasFragmentFunction(
shaderBuilder,
CustomShaderPipelineStage.FUNCTION_ID_INITIALIZE_INPUT_STRUCT_FS,
CustomShaderPipelineStage.FUNCTION_SIGNATURE_INITIALIZE_INPUT_STRUCT_FS,
[
" fsInput.attributes.color_0 = attributes.color_0;",
" fsInput.attributes.color_1 = attributes.color_1;",
]
);
});

it("only generates input lines for attributes that are used", function () {
var shaderBuilder = new ShaderBuilder();
var model = {
customShader: new CustomShader({
vertexShaderText: [
"void vertexMain(VertexInput vsInput, inout czm_modelVertexOutput vsOutput)",
"{",
" positionMC = 2.0 * vsInput.attributes.positionMC - 1.0;",
" vsOutput.positionMC = 2.0 * vsInput.attributes.positionMC - 1.0;",
"}",
].join("\n"),
fragmentShaderText: [
Expand Down

0 comments on commit 5c4f9af

Please sign in to comment.