Cg语言操作符与控制流完全指南:从基础语法到高级应用
6.1 关系操作符深度解析与应用
概念与理论
关系操作符是Cg语言中进行比较运算的基础工具,用于判断两个值之间的关系并返回布尔结果:
- 等于操作符
==:判断两个操作数是否相等 - 不等于操作符
!=:判断两个操作数是否不相等 - 大于操作符
>:判断左操作数是否大于右操作数 - 小于操作符
<:判断左操作数是否小于右操作数 - 大于等于操作符
>=:判断左操作数是否大于或等于右操作数 - 小于等于操作符
<=:判断左操作数是否小于或等于右操作数
重要特性:
- 支持标量、向量和矩阵的比较
- 向量比较按分量进行,返回布尔向量
- 精度差异可能影响比较结果
- 某些Profile对关系操作符有特殊优化
C++与Cg代码实例:关系操作符综合演示
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <Cg/cg.h>
#include <Cg/cgGL.h>
#include <iostream>
#include <vector>
class ComparisonOperatorsDemo {
private:
CGcontext context;
CGprogram vertexProgram, fragmentProgram;
CGprofile vertexProfile, fragmentProfile;
public:
ComparisonOperatorsDemo() { initializeCg(); }
~ComparisonOperatorsDemo() { cleanup(); }
private:
void initializeCg() {
context = cgCreateContext();
vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);
fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);
cgGLSetOptimalOptions(vertexProfile);
cgGLSetOptimalOptions(fragmentProfile);
}
void cleanup() {
if (vertexProgram) cgDestroyProgram(vertexProgram);
if (fragmentProgram) cgDestroyProgram(fragmentProgram);
if (context) cgDestroyContext(context);
}
public:
bool compileComparisonShaders() {
const char* vertexShader = R"(
// Cg关系操作符演示 - 顶点着色器
struct VertexInput {
float4 position : POSITION;
float2 texcoord : TEXCOORD0;
float3 color : COLOR0;
};
struct VertexOutput {
float4 position : POSITION;
float2 texcoord : TEXCOORD0;
float3 color : COLOR0;
float comparisonResults : TEXCOORD1;
};
uniform float time;
uniform int testMode;
VertexOutput main(VertexInput IN)
{
VertexOutput OUT;
OUT.position = IN.position;
OUT.texcoord = IN.texcoord;
OUT.color = IN.color;
float comparisonMask = 0.0;
if (testMode == 0) {
// 基础标量比较
float a = IN.texcoord.x;
float b = IN.texcoord.y;
// 各种关系操作符测试
bool eq = (a == b); // 等于
bool neq = (a != b); // 不等于
bool gt = (a > b); // 大于
bool lt = (a < b); // 小于
bool gte = (a >= b); // 大于等于
bool lte = (a <= b); // 小于等于
// 将布尔结果转换为数值用于可视化
comparisonMask = float(eq) * 0.1 + float(neq) * 0.2 +
float(gt) * 0.3 + float(lt) * 0.4 +
float(gte) * 0.5 + float(lte) * 0.6;
}
else if (testMode == 1) {
// 向量比较操作
float2 vecA = float2(IN.texcoord.x, IN.texcoord.y);
float2 vecB = float2(0.5, 0.5);
// 向量比较返回布尔向量
bool2 vecComparison = (vecA > vecB);
// 使用any()和all()函数处理向量比较结果
bool anyGreater = any(vecA > vecB);
bool allGreater = all(vecA > vecB);
comparisonMask = float(anyGreater) * 0.7 + float(allGreater) * 0.3;
}
else if (testMode == 2) {
// 精度相关的比较问题演示
float highPrecision = 1.0;
half mediumPrecision = 1.0;
fixed lowPrecision = 1.0;
// 理论上应该相等,但精度可能影响结果
bool highVsMedium = (highPrecision == mediumPrecision);
bool mediumVsLow = (mediumPrecision == lowPrecision);
// 使用容差进行安全比较
float tolerance = 0.001;
float valueA = IN.texcoord.x;
float valueB = 0.5;
bool safeComparison = (abs(valueA - valueB) < tolerance);
comparisonMask = float(highVsMedium) * 0.2 +
float(mediumVsLow) * 0.4 +
float(safeComparison) * 0.4;
}
else {
// 复杂比较场景:基于时间的动态阈值
float dynamicThreshold = (sin(time) + 1.0) * 0.5; // 0到1之间振荡
// 多重条件组合
bool inUpperRegion = (IN.texcoord.x > dynamicThreshold) &&
(IN.texcoord.y > dynamicThreshold);
bool inLowerRegion = (IN.texcoord.x < (1.0 - dynamicThreshold)) &&
(IN.texcoord.y < (1.0 - dynamicThreshold));
bool onDiagonal = (abs(IN.texcoord.x - IN.texcoord.y) < 0.1);
comparisonMask = float(inUpperRegion) * 0.3 +
float(inLowerRegion) * 0.5 +
float(onDiagonal) * 0.2;
}
OUT.comparisonResults = comparisonMask;
return OUT;
}
)";
const char* fragmentShader = R"(
// Cg关系操作符演示 - 片段着色器
struct FragmentInput {
float2 texcoord : TEXCOORD0;
float3 color : COLOR0;
float comparisonResults : TEXCOORD1;
};
struct FragmentOutput {
float4 color : COLOR;
};
uniform int visualizationMode;
FragmentOutput main(FragmentInput IN)
{
FragmentOutput OUT;
if (visualizationMode == 0) {
// 基于比较结果的颜色映射
float result = IN.comparisonResults;
// 使用关系操作符创建颜色带
float3 finalColor;
if (result < 0.15) {
finalColor = float3(1.0, 0.0, 0.0); // 红色:等于
}
else if (result < 0.25) {
finalColor = float3(0.0, 1.0, 0.0); // 绿色:不等于
}
else if (result < 0.35) {
finalColor = float3(0.0, 0.0, 1.0); // 蓝色:大于
}
else if (result < 0.45) {
finalColor = float3(1.0, 1.0, 0.0); // 黄色:小于
}
else if (result < 0.55) {
finalColor = float3(1.0, 0.0, 1.0); // 紫色:大于等于
}
else {
finalColor = float3(0.0, 1.0, 1.0); // 青色:小于等于
}
OUT.color = float4(finalColor, 1.0);
}
else {
// 在片段着色器中直接进行关系测试
float2 uv = IN.texcoord;
// 创建网格模式
bool2 gridMask = (frac(uv * 10.0) > 0.5);
bool gridCell = any(gridMask);
// 圆形区域检测
float2 center = float2(0.5, 0.5);
float radius = 0.3;
bool inCircle = (distance(uv, center) < radius);
// 矩形区域检测
bool inRect = (uv.x > 0.2) && (uv.x < 0.8) &&
(uv.y > 0.2) && (uv.y < 0.8);
// 组合不同区域
float3 baseColor;
if (inCircle && !gridCell) {
baseColor = float3(1.0, 0.5, 0.0); // 橙色:圆形内部
}
else if (inRect && gridCell) {
baseColor = float3(0.5, 0.0, 1.0); // 紫色:矩形网格
}
else if (inCircle || inRect) {
baseColor = float3(0.0, 1.0, 0.5); // 蓝绿色:任一区域
}
else {
baseColor = float3(0.3, 0.3, 0.3); // 灰色:其他区域
}
OUT.color = float4(baseColor, 1.0);
}
return OUT;
}
)";
vertexProgram = cgCreateProgram(context, CG_SOURCE, vertexShader,
vertexProfile, "main", nullptr);
if (!vertexProgram) return false;
cgGLLoadProgram(vertexProgram);
fragmentProgram = cgCreateProgram(context, CG_SOURCE, fragmentShader,
fragmentProfile, "main", nullptr);
if (!fragmentProgram) return false;
cgGLLoadProgram(fragmentProgram);
std::cout << "关系操作符着色器编译成功!" << std::endl;
return true;
}
void setComparisonParameters(float time, int testMode, int visualizationMode) {
CGparameter param = cgGetNamedParameter(vertexProgram, "time");
cgSetParameter1f(param, time);
param = cgGetNamedParameter(vertexProgram, "testMode");
cgSetParameter1f(param, (float)testMode);
param = cgGetNamedParameter(fragmentProgram, "visualizationMode");
cgSetParameter1f(param, (float)visualizationMode);
}
void enableShaders() {
cgGLEnableProfile(vertexProfile);
cgGLEnableProfile(fragmentProfile);
cgGLBindProgram(vertexProgram);
cgGLBindProgram(fragmentProgram);
}
void disableShaders() {
cgGLDisableProfile(vertexProfile);
cgGLDisableProfile(fragmentProfile);
}
};
int main() {
glfwInit();
GLFWwindow* window = glfwCreateWindow(800, 600, "Cg关系操作符演示", NULL, NULL);
glfwMakeContextCurrent(window);
glewInit();
std::cout << "=== Cg关系操作符演示 ===" << std::endl;
std::cout << "顶点测试模式:" << std::endl;
std::cout << "1: 基础标量比较 | 2: 向量比较 | 3: 精度比较 | 4: 动态阈值" << std::endl;
std::cout << "片段可视化模式:" << std::endl;
std::cout << "Q: 结果映射 | W: 直接测试" << std::endl;
ComparisonOperatorsDemo compDemo;
if (!compDemo.compileComparisonShaders()) {
std::cerr << "着色器编译失败" << std::endl;
return -1;
}
int testMode = 0;
int visMode = 0;
// 创建全屏四边形
unsigned int VAO, VBO;
float quadVertices[] = {
-1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
-1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
-1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
1.0f, 1.0f, 0.0f, 1.0f, 1.0f
};
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), quadVertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
// 主循环
while (!glfwWindowShouldClose(window)) {
glClear(GL_COLOR_BUFFER_BIT);
// 处理按键输入
if (glfwGetKey(window, GLFW_KEY_1) == GLFW_PRESS) testMode = 0;
if (glfwGetKey(window, GLFW_KEY_2) == GLFW_PRESS) testMode = 1;
if (glfwGetKey(window, GLFW_KEY_3) == GLFW_PRESS) testMode = 2;
if (glfwGetKey(window, GLFW_KEY_4) == GLFW_PRESS) testMode = 3;
if (glfwGetKey(window, GLFW_KEY_Q) == GLFW_PRESS) visMode = 0;
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) visMode = 1;
compDemo.setComparisonParameters((float)glfwGetTime(), testMode, visMode);
compDemo.enableShaders();
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 6);
compDemo.disableShaders();
glfwSwapBuffers(window);
glfwPollEvents();
}
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glfwTerminate();
return 0;
}
代码解释:这个程序全面演示了Cg关系操作符的各种用法。顶点着色器测试了标量比较、向量比较、精度问题和动态阈值等场景,片段着色器则将比较结果可视化。通过按键可以切换不同的测试模式,直观观察各种关系操作符的效果。
6.2 逻辑操作符系统详解
概念与理论
逻辑操作符用于组合多个布尔条件,构建复杂的逻辑判断:
- 逻辑与
&&:两个条件都为真时返回真 - 逻辑或
||:至少一个条件为真时返回真 - 逻辑非
!:对布尔值取反
重要特性:
- 支持短路求值(short-circuit evaluation)
- 可以组合多个关系表达式
- 支持向量逻辑运算(按分量)
- 某些Profile可能优化逻辑操作符的性能
C++与Cg代码实例:逻辑操作符高级应用
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <Cg/cg.h>
#include <Cg/cgGL.h>
#include <iostream>
#include <vector>
class LogicalOperatorsDemo {
private:
CGcontext context;
CGprogram vertexProgram, fragmentProgram;
CGprofile vertexProfile, fragmentProfile;
public:
LogicalOperatorsDemo() { initializeCg(); }
~LogicalOperatorsDemo() { cleanup(); }
private:
void initializeCg() {
context = cgCreateContext();
vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);
fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);
cgGLSetOptimalOptions(vertexProfile);
cgGLSetOptimalOptions(fragmentProfile);
}
void cleanup() {
if (vertexProgram) cgDestroyProgram(vertexProgram);
if (fragmentProgram) cgDestroyProgram(fragmentProgram);
if (context) cgDestroyContext(context);
}
public:
bool compileLogicalShaders() {
const char* vertexShader = R"(
// Cg逻辑操作符演示 - 顶点着色器
struct VertexInput {
float4 position : POSITION;
float2 texcoord : TEXCOORD0;
};
struct VertexOutput {
float4 position : POSITION;
float2 texcoord : TEXCOORD0;
float logicMask : TEXCOORD1;
};
uniform float time;
uniform int logicMode;
VertexOutput main(VertexInput IN)
{
VertexOutput OUT;
OUT.position = IN.position;
OUT.texcoord = IN.texcoord;
float logicValue = 0.0;
float2 uv = IN.texcoord;
if (logicMode == 0) {
// 基础逻辑操作符演示
bool conditionA = (uv.x > 0.3);
bool conditionB = (uv.y < 0.7);
bool conditionC = (distance(uv, float2(0.5, 0.5)) < 0.2);
// 逻辑与:两个条件都必须为真
bool andResult = conditionA && conditionB;
// 逻辑或:至少一个条件为真
bool orResult = conditionA || conditionB;
// 逻辑非:条件取反
bool notResult = !conditionC;
// 复杂逻辑组合
bool complexLogic = (conditionA && conditionB) || (conditionC && !conditionA);
logicValue = float(andResult) * 0.2 + float(orResult) * 0.4 +
float(notResult) * 0.6 + float(complexLogic) * 0.8;
}
else if (logicMode == 1) {
// 短路求值演示
bool shortCircuitTest = false;
// 由于短路求值,第二个条件不会被执行(如果第一个为假)
if ((uv.x < 0.0) && (expensiveFunction(uv) > 0.5)) {
shortCircuitTest = true;
}
// 使用短路求值进行安全访问
bool safeAccess = (uv.x >= 0.0 && uv.x <= 1.0) &&
(uv.y >= 0.0 && uv.y <= 1.0);
logicValue = float(shortCircuitTest) * 0.5 + float(safeAccess) * 0.5;
}
else if (logicMode == 2) {
// 向量逻辑运算
float2 threshold = float2(0.3, 0.7);
bool2 vecConditionA = (uv > threshold);
bool2 vecConditionB = (uv < float2(0.8, 0.4));
// 向量逻辑运算(按分量)
bool2 vecAnd = vecConditionA && vecConditionB;
bool2 vecOr = vecConditionA || vecConditionB;
bool2 vecNot = !vecConditionA;
// 使用any()和all()处理向量逻辑结果
bool anyTrue = any(vecAnd);
bool allTrue = all(vecOr);
logicValue = float(anyTrue) * 0.3 + float(allTrue) * 0.7;
}
else {
// 复杂逻辑系统:区域检测
float2 center1 = float2(0.3, 0.3);
float2 center2 = float2(0.7, 0.7);
float radius = 0.2;
bool inCircle1 = (distance(uv, center1) < radius);
bool inCircle2 = (distance(uv, center2) < radius);
bool inRect = (uv.x > 0.2) && (uv.x < 0.8) &&
(uv.y > 0.2) && (uv.y < 0.8);
// 排他性区域检测
bool exclusiveCircle1 = inCircle1 && !inCircle2;
bool exclusiveCircle2 = inCircle2 && !inCircle1;
bool overlapRegion = inCircle1 && inCircle2;
bool rectOnly = inRect && !(inCircle1 || inCircle2);
// 动态逻辑:基于时间变化
float pulse = sin(time * 2.0) * 0.5 + 0.5;
bool pulseActive = (pulse > 0.7);
logicValue = float(exclusiveCircle1) * 0.1 +
float(exclusiveCircle2) * 0.2 +
float(overlapRegion) * 0.3 +
float(rectOnly) * 0.4 +
float(pulseActive) * 0.5;
}
OUT.logicMask = logicValue;
return OUT;
}
// 模拟昂贵函数(用于短路求值演示)
float expensiveFunction(float2 uv)
{
// 模拟复杂计算
return length(sin(uv * 100.0));
}
)";
const char* fragmentShader = R"(
// Cg逻辑操作符演示 - 片段着色器
struct FragmentInput {
float2 texcoord : TEXCOORD0;
float logicMask : TEXCOORD1;
};
struct FragmentOutput {
float4 color : COLOR;
};
uniform int displayMode;
FragmentOutput main(FragmentInput IN)
{
FragmentOutput OUT;
float2 uv = IN.texcoord;
if (displayMode == 0) {
// 基于逻辑掩码的颜色映射
float mask = IN.logicMask;
float3 color;
if (mask < 0.1) {
color = float3(0.1, 0.1, 0.1); // 黑色:无逻辑条件满足
}
else if (mask < 0.2) {
color = float3(1.0, 0.0, 0.0); // 红色:逻辑与
}
else if (mask < 0.4) {
color = float3(0.0, 1.0, 0.0); // 绿色:逻辑或
}
else if (mask < 0.6) {
color = float3(0.0, 0.0, 1.0); // 蓝色:逻辑非
}
else if (mask < 0.8) {
color = float3(1.0, 1.0, 0.0); // 黄色:复杂逻辑
}
else {
color = float3(1.0, 0.0, 1.0); // 紫色:其他逻辑组合
}
OUT.color = float4(color, 1.0);
}
else {
// 在片段着色器中直接应用逻辑操作符
float2 gridPos = frac(uv * 8.0);
bool2 gridCell = (gridPos > 0.5);
// 创建复杂的逻辑模式
bool checkerboard = (gridCell.x != gridCell.y);
bool verticalStripes = (gridCell.x);
bool horizontalStripes = (gridCell.y);
bool border = (uv.x < 0.05 || uv.x > 0.95 || uv.y < 0.05 || uv.y > 0.95);
// 组合逻辑条件创建复杂图案
float3 finalColor;
if (border) {
finalColor = float3(1.0, 1.0, 1.0); // 白色边框
}
else if (checkerboard && !verticalStripes && !horizontalStripes) {
finalColor = float3(0.8, 0.2, 0.2); // 红色棋盘格
}
else if (verticalStripes && !horizontalStripes) {
finalColor = float3(0.2, 0.8, 0.2); // 绿色竖条纹
}
else if (horizontalStripes && !verticalStripes) {
finalColor = float3(0.2, 0.2, 0.8); // 蓝色横条纹
}
else if (verticalStripes && horizontalStripes) {
finalColor = float3(0.8, 0.8, 0.2); // 黄色交叉
}
else {
finalColor = float3(0.3, 0.3, 0.3); // 灰色背景
}
// 添加基于坐标的逻辑效果
bool inTopLeft = (uv.x < 0.5) && (uv.y > 0.5);
bool inBottomRight = (uv.x > 0.5) && (uv.y < 0.5);
if (inTopLeft) {
finalColor *= 1.5; // 增强亮度
}
else if (inBottomRight) {
finalColor *= 0.5; // 降低亮度
}
OUT.color = float4(finalColor, 1.0);
}
return OUT;
}
)";
vertexProgram = cgCreateProgram(context, CG_SOURCE, vertexShader,
vertexProfile, "main", nullptr);
if (!vertexProgram) return false;
cgGLLoadProgram(vertexProgram);
fragmentProgram = cgCreateProgram(context, CG_SOURCE, fragmentShader,
fragmentProfile, "main", nullptr);
if (!fragmentProgram) return false;
cgGLLoadProgram(fragmentProgram);
std::cout << "逻辑操作符着色器编译成功!" << std::endl;
return true;
}
void setLogicalParameters(float time, int logicMode, int displayMode) {
CGparameter param = cgGetNamedParameter(vertexProgram, "time");
cgSetParameter1f(param, time);
param = cgGetNamedParameter(vertexProgram, "logicMode");
cgSetParameter1f(param, (float)logicMode);
param = cgGetNamedParameter(fragmentProgram, "displayMode");
cgSetParameter1f(param, (float)displayMode);
}
void enableShaders() {
cgGLEnableProfile(vertexProfile);
cgGLEnableProfile(fragmentProfile);
cgGLBindProgram(vertexProgram);
cgGLBindProgram(fragmentProgram);
}
void disableShaders() {
cgGLDisableProfile(vertexProfile);
cgGLDisableProfile(fragmentProfile);
}
};
int main() {
glfwInit();
GLFWwindow* window = glfwCreateWindow(800, 600, "Cg逻辑操作符演示", NULL, NULL);
glfwMakeContextCurrent(window);
glewInit();
std::cout << "=== Cg逻辑操作符演示 ===" << std::endl;
std::cout << "逻辑模式:" << std::endl;
std::cout << "1: 基础逻辑 | 2: 短路求值 | 3: 向量逻辑 | 4: 复杂系统" << std::endl;
std::cout << "显示模式:" << std::endl;
std::cout << "Q: 掩码映射 | W: 直接逻辑" << std::endl;
LogicalOperatorsDemo logicDemo;
if (!logicDemo.compileLogicalShaders()) {
std::cerr << "着色器编译失败" << std::endl;
return -1;
}
int logicMode = 0;
int displayMode = 0;
// 创建全屏四边形(复用之前的代码)
unsigned int VAO, VBO;
float quadVertices[] = {
-1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
-1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
-1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
1.0f, 1.0f, 0.0f, 1.0f, 1.0f
};
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), quadVertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
// 主循环
while (!glfwWindowShouldClose(window)) {
glClear(GL_COLOR_BUFFER_BIT);
// 处理按键输入
if (glfwGetKey(window, GLFW_KEY_1) == GLFW_PRESS) logicMode = 0;
if (glfwGetKey(window, GLFW_KEY_2) == GLFW_PRESS) logicMode = 1;
if (glfwGetKey(window, GLFW_KEY_3) == GLFW_PRESS) logicMode = 2;
if (glfwGetKey(window, GLFW_KEY_4) == GLFW_PRESS) logicMode = 3;
if (glfwGetKey(window, GLFW_KEY_Q) == GLFW_PRESS) displayMode = 0;
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) displayMode = 1;
logicDemo.setLogicalParameters((float)glfwGetTime(), logicMode, displayMode);
logicDemo.enableShaders();
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 6);
logicDemo.disableShaders();
glfwSwapBuffers(window);
glfwPollEvents();
}
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glfwTerminate();
return 0;
}
代码解释:这个程序深入演示了Cg逻辑操作符的各种应用。包括基础逻辑运算、短路求值优化、向量逻辑运算和复杂逻辑系统。特别注意短路求值的演示,这在性能敏感的场景中非常重要。程序通过不同的逻辑模式展示了如何构建复杂的条件判断系统。
6.3 数学与移位操作符详解
概念与理论
数学操作符和移位操作符是Cg中进行数值计算的基础工具:
数学操作符:
- 算术操作符:
+(加)、-(减)、*(乘)、/(除) - 取模操作符:
%(求余数) - 递增递减:
++、--(某些Profile支持)
移位操作符:
- 左移
<<:将位模式向左移动 - 右移
>>:将位模式向右移动 - 主要用于整数操作,某些Profile支持浮点数位操作
重要特性:
- 支持向量和矩阵的逐分量运算
- 操作符重载允许标量与向量的混合运算
- 移位操作符在某些硬件上可能被模拟
C++与Cg代码实例:数学与移位操作符应用
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <Cg/cg.h>
#include <Cg/cgGL.h>
#include <iostream>
#include <vector>
class MathShiftDemo {
private:
CGcontext context;
CGprogram vertexProgram, fragmentProgram;
CGprofile vertexProfile, fragmentProfile;
public:
MathShiftDemo() { initializeCg(); }
~MathShiftDemo() { cleanup(); }
private:
void initializeCg() {
context = cgCreateContext();
vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);
fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);
cgGLSetOptimalOptions(vertexProfile);
cgGLSetOptimalOptions(fragmentProfile);
}
void cleanup() {
if (vertexProgram) cgDestroyProgram(vertexProgram);
if (fragmentProgram) cgDestroyProgram(fragmentProgram);
if (context) cgDestroyContext(context);
}
public:
bool compileMathShiftShaders() {
const char* vertexShader = R"(
// Cg数学与移位操作符演示 - 顶点着色器
struct VertexInput {
float4 position : POSITION;
float2 texcoord : TEXCOORD0;
};
struct VertexOutput {
float4 position : POSITION;
float2 texcoord : TEXCOORD0;
float mathResults : TEXCOORD1;
};
uniform float time;
uniform int operationMode;
VertexOutput main(VertexInput IN)
{
VertexOutput OUT;
OUT.position = IN.position;
OUT.texcoord = IN.texcoord;
float result = 0.0;
float2 uv = IN.texcoord;
if (operationMode == 0) {
// 基础算术操作符
float a = uv.x;
float b = uv.y;
// 四则运算
float addition = a + b;
float subtraction = a - b;
float multiplication = a * b;
float division = (b != 0.0) ? (a / b) : 0.0;
// 取模运算
float modulo = fmod(a * 10.0, 3.0);
result = (addition * 0.1 + subtraction * 0.2 +
multiplication * 0.3 + division * 0.4 + modulo * 0.5) / 5.0;
}
else if (operationMode == 1) {
// 向量和矩阵运算
float2 vecA = float2(uv.x, uv.y);
float2 vecB = float2(0.3, 0.7);
// 向量运算
float2 vecAdd = vecA + vecB;
float2 vecMul = vecA * vecB;
float2 vecDiv = vecA / (vecB + 0.001); // 避免除零
// 点积和叉积(2D叉积是标量)
float dotProduct = dot(vecA, vecB);
float crossProduct = vecA.x * vecB.y - vecA.y * vecB.x;
result = (dotProduct + crossProduct) * 0.5;
}
else if (operationMode == 2) {
// 移位操作符演示
int intValue = int(uv.x * 255.0); // 将0-1映射到0-255
// 左移:相当于乘以2的n次方
int leftShift1 = intValue << 1; // 乘以2
int leftShift2 = intValue << 2; // 乘以4
int leftShift3 = intValue << 3; // 乘以8
// 右移:相当于除以2的n次方(向下取整)
int rightShift1 = intValue >> 1; // 除以2
int rightShift2 = intValue >> 2; // 除以4
int rightShift3 = intValue >> 3; // 除以8
// 组合移位结果
float shiftResult = float(leftShift1 + leftShift2 + leftShift3 +
rightShift1 + rightShift2 + rightShift3) / 1530.0;
result = shiftResult;
}
else {
// 复杂数学运算组合
float2 polarCoord;
polarCoord.x = atan2(uv.y - 0.5, uv.x - 0.5); // 角度
polarCoord.y = length(uv - float2(0.5, 0.5)); // 半径
// 使用数学操作符创建复杂模式
float spiral = polarCoord.x * 3.0 + polarCoord.y * 10.0 + time * 2.0;
float waves = sin(uv.x * 20.0 + time) * cos(uv.y * 15.0 - time);
float grid = frac(uv.x * 8.0) * frac(uv.y * 8.0);
// 数学运算组合
float complexMath = (sin(spiral) + waves) * grid;
complexMath = fmod(abs(complexMath * 10.0), 1.0);
result = complexMath;
}
OUT.mathResults = result;
return OUT;
}
)";
const char* fragmentShader = R"(
// Cg数学与移位操作符演示 - 片段着色器
struct FragmentInput {
float2 texcoord : TEXCOORD0;
float mathResults : TEXCOORD1;
};
struct FragmentOutput {
float4 color : COLOR;
};
uniform int visualizationType;
// 数学工具函数
float3 hueToRGB(float hue)
{
float3 rgb = frac(hue + float3(0.0, 2.0/3.0, 1.0/3.0));
rgb = abs(rgb * 6.0 - 3.0) - 1.0;
return clamp(rgb, 0.0, 1.0);
}
FragmentOutput main(FragmentInput IN)
{
FragmentOutput OUT;
float2 uv = IN.texcoord;
if (visualizationType == 0) {
// 基于数学结果的直接可视化
float value = IN.mathResults;
OUT.color = float4(value, value, value, 1.0);
}
else if (visualizationType == 1) {
// 彩色数学可视化
float value = IN.mathResults;
float3 color = hueToRGB(value);
OUT.color = float4(color, 1.0);
}
else {
// 在片段着色器中进行实时数学运算
float2 coord = uv * 4.0 - 2.0; // 扩展到-2到2范围
// 复数迭代(Mandelbrot集合简化版)
float2 z = float2(0.0, 0.0);
float2 c = coord;
int iterations = 0;
const int maxIterations = 20;
for (int i = 0; i < maxIterations; i++) {
// 复数乘法: (a+bi)^2 = (a^2 - b^2) + 2abi
float2 zSquared;
zSquared.x = z.x * z.x - z.y * z.y;
zSquared.y = 2.0 * z.x * z.y;
// 复数加法: z = z^2 + c
z = zSquared + c;
// 检查是否发散
if (length(z) > 2.0) {
iterations = i;
break;
}
iterations = i;
}
float escapeValue = float(iterations) / float(maxIterations);
float3 mandelbrotColor = hueToRGB(escapeValue);
OUT.color = float4(mandelbrotColor, 1.0);
}
return OUT;
}
)";
vertexProgram = cgCreateProgram(context, CG_SOURCE, vertexShader,
vertexProfile, "main", nullptr);
if (!vertexProgram) return false;
cgGLLoadProgram(vertexProgram);
fragmentProgram = cgCreateProgram(context, CG_SOURCE, fragmentShader,
fragmentProfile, "main", nullptr);
if (!fragmentProgram) return false;
cgGLLoadProgram(fragmentProgram);
std::cout << "数学与移位操作符着色器编译成功!" << std::endl;
return true;
}
void setMathShiftParameters(float time, int operationMode, int visualizationType) {
CGparameter param = cgGetNamedParameter(vertexProgram, "time");
cgSetParameter1f(param, time);
param = cgGetNamedParameter(vertexProgram, "operationMode");
cgSetParameter1f(param, (float)operationMode);
param = cgGetNamedParameter(fragmentProgram, "visualizationType");
cgSetParameter1f(param, (float)visualizationType);
}
void enableShaders() {
cgGLEnableProfile(vertexProfile);
cgGLEnableProfile(fragmentProfile);
cgGLBindProgram(vertexProgram);
cgGLBindProgram(fragmentProgram);
}
void disableShaders() {
cgGLDisableProfile(vertexProfile);
cgGLDisableProfile(fragmentProfile);
}
};
int main() {
glfwInit();
GLFWwindow* window = glfwCreateWindow(800, 600, "Cg数学与移位操作符演示", NULL, NULL);
glfwMakeContextCurrent(window);
glewInit();
std::cout << "=== Cg数学与移位操作符演示 ===" << std::endl;
std::cout << "操作模式:" << std::endl;
std::cout << "1: 基础算术 | 2: 向量矩阵 | 3: 移位操作 | 4: 复杂数学" << std::endl;
std::cout << "可视化类型:" << std::endl;
std::cout << "Q: 灰度 | W: 彩色 | E: 实时数学" << std::endl;
MathShiftDemo mathDemo;
if (!mathDemo.compileMathShiftShaders()) {
std::cerr << "着色器编译失败" << std::endl;
return -1;
}
int operationMode = 0;
int visType = 0;
// 创建全屏四边形
unsigned int VAO, VBO;
float quadVertices[] = {
-1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
-1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
-1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
1.0f, 1.0f, 0.0f, 1.0f, 1.0f
};
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), quadVertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
// 主循环
while (!glfwWindowShouldClose(window)) {
glClear(GL_COLOR_BUFFER_BIT);
// 处理按键输入
if (glfwGetKey(window, GLFW_KEY_1) == GLFW_PRESS) operationMode = 0;
if (glfwGetKey(window, GLFW_KEY_2) == GLFW_PRESS) operationMode = 1;
if (glfwGetKey(window, GLFW_KEY_3) == GLFW_PRESS) operationMode = 2;
if (glfwGetKey(window, GLFW_KEY_4) == GLFW_PRESS) operationMode = 3;
if (glfwGetKey(window, GLFW_KEY_Q) == GLFW_PRESS) visType = 0;
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) visType = 1;
if (glfwGetKey(window, GLFW_KEY_E) == GLFW_PRESS) visType = 2;
mathDemo.setMathShiftParameters((float)glfwGetTime(), operationMode, visType);
mathDemo.enableShaders();
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 6);
mathDemo.disableShaders();
glfwSwapBuffers(window);
glfwPollEvents();
}
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glfwTerminate();
return 0;
}
代码解释:这个程序全面演示了Cg数学操作符和移位操作符的应用。包括基础算术运算、向量矩阵运算、移位操作和复杂数学系统。特别注意片段着色器中的Mandelbrot集合计算,展示了如何在实时渲染中进行复杂的数学迭代。移位操作符部分演示了位操作在图形编程中的应用。
6.4 Swizzle操作符与条件操作符
概念与理论
Swizzle操作符和条件操作符是Cg语言中极具特色的功能:
Swizzle操作符:
- 允许重新排列和复制向量的分量
- 语法:
vector.xyzw或vector.rgba - 支持分量重排、复制和混合
条件操作符:
- 三元操作符:
condition ? valueIfTrue : valueIfFalse - 提供紧凑的条件赋值语法
- 在某些情况下比if-else语句更高效
C++与Cg代码实例:Swizzle与条件操作符实战
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <Cg/cg.h>
#include <Cg/cgGL.h>
#include <iostream>
#include <vector>
class SwizzleConditionalDemo {
private:
CGcontext context;
CGprogram vertexProgram, fragmentProgram;
CGprofile vertexProfile, fragmentProfile;
public:
SwizzleConditionalDemo() { initializeCg(); }
~SwizzleConditionalDemo() { cleanup(); }
private:
void initializeCg() {
context = cgCreateContext();
vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);
fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);
cgGLSetOptimalOptions(vertexProfile);
cgGLSetOptimalOptions(fragmentProfile);
}
void cleanup() {
if (vertexProgram) cgDestroyProgram(vertexProgram);
if (fragmentProgram) cgDestroyProgram(fragmentProgram);
if (context) cgDestroyContext(context);
}
public:
bool compileSwizzleConditionalShaders() {
const char* vertexShader = R"(
// Cg Swizzle与条件操作符演示 - 顶点着色器
struct VertexInput {
float4 position : POSITION;
float2 texcoord : TEXCOORD0;
float3 color : COLOR0;
};
struct VertexOutput {
float4 position : POSITION;
float2 texcoord : TEXCOORD0;
float3 color : COLOR0;
float swizzleMask : TEXCOORD1;
};
uniform float time;
uniform int demoMode;
VertexOutput main(VertexInput IN)
{
VertexOutput OUT;
OUT.position = IN.position;
OUT.texcoord = IN.texcoord;
OUT.color = IN.color;
float maskValue = 0.0;
float4 vector = float4(IN.texcoord.x, IN.texcoord.y,
length(IN.texcoord - 0.5), 1.0);
if (demoMode == 0) {
// 基础Swizzle操作
float2 xySwizzle = vector.xy; // 提取前两个分量
float4 fullSwizzle = vector.xyzw; // 完整复制
float4 reversed = vector.wzyx; // 分量反转
float4 duplicated = vector.xxyy; // 分量复制
maskValue = (xySwizzle.x + xySwizzle.y +
reversed.x + duplicated.x) * 0.25;
}
else if (demoMode == 1) {
// 高级Swizzle模式
float4 colorSwizzle = vector.bgra; // 颜色通道重排
float4 customPattern = vector.xzxz; // 自定义模式
float4 mixedSwizzle = vector.xyyx; // 混合模式
// Swizzle在计算中的应用
float dotProduct = dot(vector.xy, vector.zw);
float crossProduct = vector.x * vector.w - vector.y * vector.z;
maskValue = (colorSwizzle.r + customPattern.x +
mixedSwizzle.x + dotProduct + crossProduct) * 0.2;
}
else if (demoMode == 2) {
// 条件操作符基础
float threshold = 0.5;
// 简单的三元操作符
float simpleConditional = (vector.x > threshold) ? 1.0 : 0.0;
// 嵌套条件操作符
float nestedConditional = (vector.x > 0.7) ? 1.0 :
(vector.x > 0.3) ? 0.5 : 0.0;
// 向量条件操作符
float2 vecConditional = (vector.xy > float2(0.4, 0.6)) ?
float2(1.0, 0.5) : float2(0.2, 0.8);
maskValue = simpleConditional * 0.3 + nestedConditional * 0.3 +
(vecConditional.x + vecConditional.y) * 0.2;
}
else {
// Swizzle与条件操作符结合
float4 baseVector = vector;
// 基于条件的Swizzle选择
float4 swizzled = (time % 2.0 > 1.0) ? baseVector.xyzw : baseVector.wzyx;
// 动态Swizzle模式
int swizzlePattern = int(time) % 4;
float4 dynamicSwizzle;
if (swizzlePattern == 0) dynamicSwizzle = baseVector.xyxy;
else if (swizzlePattern == 1) dynamicSwizzle = baseVector.yxyx;
else if (swizzlePattern == 2) dynamicSwizzle = baseVector.xxyy;
else dynamicSwizzle = baseVector.yyxx;
// 条件Swizzle操作
bool useRG = (baseVector.x > baseVector.y);
float2 selectedChannels = useRG ? baseVector.rg : baseVector.ba;
maskValue = (swizzled.x + dynamicSwizzle.x + selectedChannels.x) * 0.33;
}
OUT.swizzleMask = maskValue;
return OUT;
}
)";
const char* fragmentShader = R"(
// Cg Swizzle与条件操作符演示 - 片段着色器
struct FragmentInput {
float2 texcoord : TEXCOORD0;
float3 color : COLOR0;
float swizzleMask : TEXCOORD1;
};
struct FragmentOutput {
float4 color : COLOR;
};
uniform int renderMode;
FragmentOutput main(FragmentInput IN)
{
FragmentOutput OUT;
float2 uv = IN.texcoord;
if (renderMode == 0) {
// Swizzle操作符可视化
float4 baseColor = float4(uv.x, uv.y, 0.5, 1.0);
// 应用不同的Swizzle模式
float4 swizzledColor;
// RGB转BGR(颜色通道交换)
swizzledColor.rgb = baseColor.bgr;
swizzledColor.a = baseColor.a;
// 或者使用更复杂的Swizzle
float4 complexSwizzle = baseColor.gbar; // 绿色、蓝色、alpha、红色
OUT.color = complexSwizzle;
}
else if (renderMode == 1) {
// 条件操作符可视化
float2 coord = uv * 2.0 - 1.0; // 转换到-1到1范围
// 使用条件操作符创建图案
float3 pixelColor;
// 圆形检测
float radius = length(coord);
pixelColor = (radius < 0.8) ?
float3(1.0, 0.0, 0.0) : // 红色圆形
float3(0.0, 0.0, 1.0); // 蓝色背景
// 添加十字线
float lineWidth = 0.02;
bool isVerticalLine = (abs(coord.x) < lineWidth);
bool isHorizontalLine = (abs(coord.y) < lineWidth);
pixelColor = (isVerticalLine || isHorizontalLine) ?
float3(1.0, 1.0, 1.0) : // 白色十字线
pixelColor;
// 添加四个象限的不同颜色
bool inFirstQuadrant = (coord.x > 0.0 && coord.y > 0.0);
bool inSecondQuadrant = (coord.x < 0.0 && coord.y > 0.0);
bool inThirdQuadrant = (coord.x < 0.0 && coord.y < 0.0);
bool inFourthQuadrant = (coord.x > 0.0 && coord.y < 0.0);
float3 quadrantColor =
inFirstQuadrant ? float3(1.0, 1.0, 0.0) : // 黄色
inSecondQuadrant ? float3(0.0, 1.0, 1.0) : // 青色
inThirdQuadrant ? float3(1.0, 0.0, 1.0) : // 紫色
inFourthQuadrant ? float3(0.5, 0.5, 0.5) : // 灰色
pixelColor;
// 混合原始颜色和象限颜色
pixelColor = (radius < 0.5) ? quadrantColor : pixelColor;
OUT.color = float4(pixelColor, 1.0);
}
else {
// Swizzle与条件操作符结合应用
float2 polar;
polar.x = atan2(uv.y - 0.5, uv.x - 0.5) / 3.14159; // 归一化角度
polar.y = length(uv - 0.5); // 半径
// 基于角度的条件颜色选择
float3 angleBasedColor;
angleBasedColor = (polar.x < -0.5) ? float3(1.0, 0.0, 0.0) :
(polar.x < 0.0) ? float3(0.0, 1.0, 0.0) :
(polar.x < 0.5) ? float3(0.0, 0.0, 1.0) :
float3(1.0, 1.0, 0.0);
// 使用Swizzle创建颜色变体
float3 swizzledColor1 = angleBasedColor.rgb;
float3 swizzledColor2 = angleBasedColor.brg;
float3 swizzledColor3 = angleBasedColor.gbr;
// 基于半径的条件选择
float3 finalColor = (polar.y < 0.2) ? swizzledColor1 :
(polar.y < 0.4) ? swizzledColor2 :
swizzledColor3;
// 添加动态效果
float pulse = sin(polar.x * 10.0 + polar.y * 20.0) * 0.5 + 0.5;
finalColor = (pulse > 0.7) ? finalColor : finalColor * 0.5;
OUT.color = float4(finalColor, 1.0);
}
return OUT;
}
)";
vertexProgram = cgCreateProgram(context, CG_SOURCE, vertexShader,
vertexProfile, "main", nullptr);
if (!vertexProgram) return false;
cgGLLoadProgram(vertexProgram);
fragmentProgram = cgCreateProgram(context, CG_SOURCE, fragmentShader,
fragmentProfile, "main", nullptr);
if (!fragmentProgram) return false;
cgGLLoadProgram(fragmentProgram);
std::cout << "Swizzle与条件操作符着色器编译成功!" << std::endl;
return true;
}
void setSwizzleConditionalParameters(float time, int demoMode, int renderMode) {
CGparameter param = cgGetNamedParameter(vertexProgram, "time");
cgSetParameter1f(param, time);
param = cgGetNamedParameter(vertexProgram, "demoMode");
cgSetParameter1f(param, (float)demoMode);
param = cgGetNamedParameter(fragmentProgram, "renderMode");
cgSetParameter1f(param, (float)renderMode);
}
void enableShaders() {
cgGLEnableProfile(vertexProfile);
cgGLEnableProfile(fragmentProfile);
cgGLBindProgram(vertexProgram);
cgGLBindProgram(fragmentProgram);
}
void disableShaders() {
cgGLDisableProfile(vertexProfile);
cgGLDisableProfile(fragmentProfile);
}
};
int main() {
glfwInit();
GLFWwindow* window = glfwCreateWindow(800, 600, "Cg Swizzle与条件操作符演示", NULL, NULL);
glfwMakeContextCurrent(window);
glewInit();
std::cout << "=== Cg Swizzle与条件操作符演示 ===" << std::endl;
std::cout << "演示模式:" << std::endl;
std::cout << "1: 基础Swizzle | 2: 高级Swizzle | 3: 条件操作符 | 4: 结合应用" << std::endl;
std::cout << "渲染模式:" << std::endl;
std::cout << "Q: Swizzle可视化 | W: 条件操作符 | E: 结合应用" << std::endl;
SwizzleConditionalDemo swizzleDemo;
if (!swizzleDemo.compileSwizzleConditionalShaders()) {
std::cerr << "着色器编译失败" << std::endl;
return -1;
}
int demoMode = 0;
int renderMode = 0;
// 创建全屏四边形
unsigned int VAO, VBO;
float quadVertices[] = {
-1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
-1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
-1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
1.0f, 1.0f, 0.0f, 1.0f, 1.0f
};
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), quadVertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
// 主循环
while (!glfwWindowShouldClose(window)) {
glClear(GL_COLOR_BUFFER_BIT);
// 处理按键输入
if (glfwGetKey(window, GLFW_KEY_1) == GLFW_PRESS) demoMode = 0;
if (glfwGetKey(window, GLFW_KEY_2) == GLFW_PRESS) demoMode = 1;
if (glfwGetKey(window, GLFW_KEY_3) == GLFW_PRESS) demoMode = 2;
if (glfwGetKey(window, GLFW_KEY_4) == GLFW_PRESS) demoMode = 3;
if (glfwGetKey(window, GLFW_KEY_Q) == GLFW_PRESS) renderMode = 0;
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) renderMode = 1;
if (glfwGetKey(window, GLFW_KEY_E) == GLFW_PRESS) renderMode = 2;
swizzleDemo.setSwizzleConditionalParameters((float)glfwGetTime(), demoMode, renderMode);
swizzleDemo.enableShaders();
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 6);
swizzleDemo.disableShaders();
glfwSwapBuffers(window);
glfwPollEvents();
}
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glfwTerminate();
return 0;
}
代码解释:这个程序深入演示了Cg的Swizzle操作符和条件操作符。Swizzle操作符展示了分量重排、复制和混合的各种技巧,条件操作符演示了紧凑的条件赋值语法。特别展示了如何将两者结合使用来创建复杂的渲染效果,包括基于极坐标的颜色选择和动态Swizzle模式。
6.5 操作符优先级与复杂表达式
概念与理论
操作符优先级决定了复杂表达式中各个操作符的执行顺序:
Cg操作符优先级(从高到低):
()- 括号分组[]- 数组下标、函数调用、结构成员访问!-(负号)++--- 一元操作符*/%- 乘性操作符+-- 加性操作符<<>>- 移位操作符<<=>>=- 关系操作符==!=- 相等性操作符&- 位与^- 位异或|- 位或&&- 逻辑与||- 逻辑或?:- 条件操作符=+=-=*=/=%=- 赋值操作符
最佳实践:
- 使用括号明确表达意图,避免依赖优先级记忆
- 复杂表达式适当分解为多个简单表达式
- 注意操作符结合性(左结合或右结合)
C++与Cg代码实例:操作符优先级与复杂表达式
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <Cg/cg.h>
#include <Cg/cgGL.h>
#include <iostream>
#include <vector>
class OperatorPrecedenceDemo {
private:
CGcontext context;
CGprogram vertexProgram, fragmentProgram;
CGprofile vertexProfile, fragmentProfile;
public:
OperatorPrecedenceDemo() { initializeCg(); }
~OperatorPrecedenceDemo() { cleanup(); }
private:
void initializeCg() {
context = cgCreateContext();
vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);
fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);
cgGLSetOptimalOptions(vertexProfile);
cgGLSetOptimalOptions(fragmentProfile);
}
void cleanup() {
if (vertexProgram) cgDestroyProgram(vertexProgram);
if (fragmentProgram) cgDestroyProgram(fragmentProgram);
if (context) cgDestroyContext(context);
}
public:
bool compilePrecedenceShaders() {
const char* vertexShader = R"(
// Cg操作符优先级演示 - 顶点着色器
struct VertexInput {
float4 position : POSITION;
float2 texcoord : TEXCOORD0;
};
struct VertexOutput {
float4 position : POSITION;
float2 texcoord : TEXCOORD0;
float precedenceResults : TEXCOORD1;
};
uniform float time;
uniform int precedenceCase;
VertexOutput main(VertexInput IN)
{
VertexOutput OUT;
OUT.position = IN.position;
OUT.texcoord = IN.texcoord;
float result = 0.0;
float a = IN.texcoord.x;
float b = IN.texcoord.y;
float c = length(IN.texcoord - 0.5);
if (precedenceCase == 0) {
// 案例1:常见优先级错误
// 错误理解:a + b * c 可能被误解为 (a + b) * c
float withoutParentheses = a + b * c; // 实际:a + (b * c)
float withParentheses = (a + b) * c; // 明确分组
result = abs(withoutParentheses - withParentheses) * 10.0;
}
else if (precedenceCase == 1) {
// 案例2:逻辑操作符优先级
bool complexLogic1 = a > 0.5 && b < 0.5 || c > 0.3; // 模糊的逻辑
bool complexLogic2 = (a > 0.5 && b < 0.5) || c > 0.3; // 明确分组
bool complexLogic3 = a > 0.5 && (b < 0.5 || c > 0.3); // 不同的分组
result = float(complexLogic1) * 0.2 +
float(complexLogic2) * 0.4 +
float(complexLogic3) * 0.6;
}
else if (precedenceCase == 2) {
// 案例3:条件操作符优先级
float conditional1 = a > b ? a * 2.0 : b * 2.0 + 1.0; // 可能意外
float conditional2 = (a > b) ? (a * 2.0) : (b * 2.0 + 1.0); // 明确
// 嵌套条件操作符
float nestedConditional = (a > 0.7) ? 1.0 :
(b > 0.5) ? 0.5 :
(c > 0.3) ? 0.2 : 0.0;
result = conditional1 * 0.2 + conditional2 * 0.2 + nestedConditional * 0.6;
}
else {
// 案例4:复杂表达式优化
// 原始复杂表达式
float complexExpr1 = a * b + c * a - b / c + sin(a) * cos(b);
// 使用括号明确优先级
float complexExpr2 = (a * b) + (c * a) - (b / c) + (sin(a) * cos(b));
// 分解为多个步骤(可能更清晰)
float step1 = a * b;
float step2 = c * a;
float step3 = b / c;
float step4 = sin(a) * cos(b);
float decomposed = step1 + step2 - step3 + step4;
result = (complexExpr1 + complexExpr2 + decomposed) / 3.0;
}
OUT.precedenceResults = result;
return OUT;
}
)";
const char* fragmentShader = R"(
// Cg操作符优先级演示 - 片段着色器
struct FragmentInput {
float2 texcoord : TEXCOORD0;
float precedenceResults : TEXCOORD1;
};
struct FragmentOutput {
float4 color : COLOR;
};
uniform int visualizationStyle;
// 颜色渐变函数
float3 heatMap(float value)
{
float3 color;
if (value < 0.25) {
color = lerp(float3(0.0, 0.0, 1.0), float3(0.0, 1.0, 1.0), value * 4.0);
}
else if (value < 0.5) {
color = lerp(float3(0.0, 1.0, 1.0), float3(0.0, 1.0, 0.0), (value - 0.25) * 4.0);
}
else if (value < 0.75) {
color = lerp(float3(0.0, 1.0, 0.0), float3(1.0, 1.0, 0.0), (value - 0.5) * 4.0);
}
else {
color = lerp(float3(1.0, 1.0, 0.0), float3(1.0, 0.0, 0.0), (value - 0.75) * 4.0);
}
return color;
}
FragmentOutput main(FragmentInput IN)
{
FragmentOutput OUT;
float2 uv = IN.texcoord;
if (visualizationStyle == 0) {
// 直接结果显示
float value = IN.precedenceResults;
float3 color = heatMap(value);
OUT.color = float4(color, 1.0);
}
else {
// 在片段着色器中演示优先级问题
float a = uv.x;
float b = uv.y;
// 容易出错的复杂表达式
float trickyExpression1 = a * a + b * b * 2.0 + 1.0; // a² + 2b² + 1
float trickyExpression2 = (a * a) + (b * b * 2.0) + 1.0; // 明确分组
// 条件表达式中的优先级问题
float conditionalResult = a > 0.5 ? a * a : b * b + 1.0; // 可能不是预期的
float safeConditional = (a > 0.5) ? (a * a) : (b * b + 1.0); // 安全版本
// 逻辑表达式优先级
bool logicResult1 = a > 0.3 && b < 0.7 || a < 0.1; // 模糊
bool logicResult2 = (a > 0.3 && b < 0.7) || a < 0.1; // 明确
bool logicResult3 = a > 0.3 && (b < 0.7 || a < 0.1); // 另一种分组
// 组合结果显示
float combinedResult = (trickyExpression1 + trickyExpression2 +
conditionalResult + safeConditional +
float(logicResult1) + float(logicResult2) +
float(logicResult3)) / 7.0;
float3 finalColor = heatMap(combinedResult);
OUT.color = float4(finalColor, 1.0);
}
return OUT;
}
)";
vertexProgram = cgCreateProgram(context, CG_SOURCE, vertexShader,
vertexProfile, "main", nullptr);
if (!vertexProgram) return false;
cgGLLoadProgram(vertexProgram);
fragmentProgram = cgCreateProgram(context, CG_SOURCE, fragmentShader,
fragmentProfile, "main", nullptr);
if (!fragmentProgram) return false;
cgGLLoadProgram(fragmentProgram);
std::cout << "操作符优先级着色器编译成功!" << std::endl;
return true;
}
void setPrecedenceParameters(float time, int precedenceCase, int visualizationStyle) {
CGparameter param = cgGetNamedParameter(vertexProgram, "time");
cgSetParameter1f(param, time);
param = cgGetNamedParameter(vertexProgram, "precedenceCase");
cgSetParameter1f(param, (float)precedenceCase);
param = cgGetNamedParameter(fragmentProgram, "visualizationStyle");
cgSetParameter1f(param, (float)visualizationStyle);
}
void enableShaders() {
cgGLEnableProfile(vertexProfile);
cgGLEnableProfile(fragmentProfile);
cgGLBindProgram(vertexProgram);
cgGLBindProgram(fragmentProgram);
}
void disableShaders() {
cgGLDisableProfile(vertexProfile);
cgGLDisableProfile(fragmentProfile);
}
};
int main() {
glfwInit();
GLFWwindow* window = glfwCreateWindow(800, 600, "Cg操作符优先级演示", NULL, NULL);
glfwMakeContextCurrent(window);
glewInit();
std::cout << "=== Cg操作符优先级演示 ===" << std::endl;
std::cout << "优先级案例:" << std::endl;
std::cout << "1: 算术优先级 | 2: 逻辑优先级 | 3: 条件优先级 | 4: 复杂表达式" << std::endl;
std::cout << "可视化样式:" << std::endl;
std::cout << "Q: 直接显示 | W: 片段计算" << std::endl;
OperatorPrecedenceDemo precedenceDemo;
if (!precedenceDemo.compilePrecedenceShaders()) {
std::cerr << "着色器编译失败" << std::endl;
return -1;
}
int precedenceCase = 0;
int visStyle = 0;
// 创建全屏四边形
unsigned int VAO, VBO;
float quadVertices[] = {
-1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
-1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
-1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
1.0f, 1.0f, 0.0f, 1.0f, 1.0f
};
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), quadVertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
// 主循环
while (!glfwWindowShouldClose(window)) {
glClear(GL_COLOR_BUFFER_BIT);
// 处理按键输入
if (glfwGetKey(window, GLFW_KEY_1) == GLFW_PRESS) precedenceCase = 0;
if (glfwGetKey(window, GLFW_KEY_2) == GLFW_PRESS) precedenceCase = 1;
if (glfwGetKey(window, GLFW_KEY_3) == GLFW_PRESS) precedenceCase = 2;
if (glfwGetKey(window, GLFW_KEY_4) == GLFW_PRESS) precedenceCase = 3;
if (glfwGetKey(window, GLFW_KEY_Q) == GLFW_PRESS) visStyle = 0;
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) visStyle = 1;
precedenceDemo.setPrecedenceParameters((float)glfwGetTime(), precedenceCase, visStyle);
precedenceDemo.enableShaders();
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 6);
precedenceDemo.disableShaders();
glfwSwapBuffers(window);
glfwPollEvents();
}
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glfwTerminate();
return 0;
}
代码解释:这个程序专门演示了Cg操作符优先级的重要性和常见陷阱。通过对比有括号和无括号的表达式,展示了优先级如何影响计算结果。特别强调了在复杂逻辑表达式和条件表达式中使用括号的重要性,以避免难以发现的错误。
6.6 控制流语句全面解析
概念与理论
控制流语句决定了Cg程序的执行流程,是构建复杂着色器逻辑的基础:
条件语句:
if-else:基础条件分支switch-case:多路分支(某些Profile支持)
循环语句:
for:确定次数的循环while:条件循环do-while:后测试循环
控制转移:
break:退出循环或switchcontinue:跳过当前循环迭代return:从函数返回
重要特性:
- 某些Profile对控制流有严格限制
- 循环展开可能影响性能
- 动态循环在某些硬件上可能不被支持
C++与Cg代码实例:控制流语句高级应用
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <Cg/cg.h>
#include <Cg/cgGL.h>
#include <iostream>
#include <vector>
class ControlFlowDemo {
private:
CGcontext context;
CGprogram vertexProgram, fragmentProgram;
CGprofile vertexProfile, fragmentProfile;
public:
ControlFlowDemo() { initializeCg(); }
~ControlFlowDemo() { cleanup(); }
private:
void initializeCg() {
context = cgCreateContext();
vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);
fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);
cgGLSetOptimalOptions(vertexProfile);
cgGLSetOptimalOptions(fragmentProfile);
}
void cleanup() {
if (vertexProgram) cgDestroyProgram(vertexProgram);
if (fragmentProgram) cgDestroyProgram(fragmentProgram);
if (context) cgDestroyContext(context);
}
public:
bool compileControlFlowShaders() {
const char* vertexShader = R"(
// Cg控制流语句演示 - 顶点着色器
struct VertexInput {
float4 position : POSITION;
float2 texcoord : TEXCOORD0;
};
struct VertexOutput {
float4 position : POSITION;
float2 texcoord : TEXCOORD0;
float controlFlowMask : TEXCOORD1;
};
uniform float time;
uniform int flowPattern;
VertexOutput main(VertexInput IN)
{
VertexOutput OUT;
OUT.position = IN.position;
OUT.texcoord = IN.texcoord;
float result = 0.0;
float2 uv = IN.texcoord;
if (flowPattern == 0) {
// 基础if-else语句
float value = 0.0;
if (uv.x < 0.2) {
value = 0.1; // 区域1
}
else if (uv.x < 0.4) {
value = 0.2; // 区域2
}
else if (uv.x < 0.6) {
value = 0.3; // 区域3
}
else if (uv.x < 0.8) {
value = 0.4; // 区域4
}
else {
value = 0.5; // 区域5
}
// 添加垂直分区
if (uv.y < 0.33) {
value += 0.05; // 底部区域
}
else if (uv.y < 0.66) {
value += 0.10; // 中部区域
}
else {
value += 0.15; // 顶部区域
}
result = value;
}
else if (flowPattern == 1) {
// for循环演示:创建网格模式
float gridValue = 0.0;
const int gridSize = 4;
for (int i = 0; i < gridSize; i++) {
for (int j = 0; j < gridSize; j++) {
float2 cellMin = float2(i, j) / float(gridSize);
float2 cellMax = float2(i + 1, j + 1) / float(gridSize);
if (uv.x >= cellMin.x && uv.x < cellMax.x &&
uv.y >= cellMin.y && uv.y < cellMax.y) {
// 棋盘格模式
if ((i + j) % 2 == 0) {
gridValue = 0.7;
} else {
gridValue = 0.3;
}
break; // 找到对应单元格,退出内层循环
}
}
}
result = gridValue;
}
else if (flowPattern == 2) {
// while循环演示:光线步进
float2 rayPos = uv;
float2 rayDir = normalize(float2(0.5, 0.5) - uv);
float accumulated = 0.0;
int steps = 0;
const int maxSteps = 10;
while (steps < maxSteps &&
rayPos.x >= 0.0 && rayPos.x <= 1.0 &&
rayPos.y >= 0.0 && rayPos.y <= 1.0) {
// 检查是否在圆内
float2 toCenter = rayPos - float2(0.5, 0.5);
if (length(toCenter) < 0.2) {
accumulated += 0.1;
break; // 命中目标,提前退出
}
// 继续步进
rayPos += rayDir * 0.05;
steps++;
}
// 使用continue的示例
float skipSum = 0.0;
for (int i = 0; i < 8; i++) {
if (i % 3 == 0) {
continue; // 跳过3的倍数
}
skipSum += 0.1;
}
result = accumulated + skipSum * 0.5;
}
else {
// 复杂控制流:分形计算
float2 c = (uv - 0.5) * 2.5; // 缩放坐标
float2 z = float2(0.0, 0.0);
float iter = 0.0;
const float maxIter = 20.0;
for (float i = 0.0; i < maxIter; i++) {
// 曼德博集合迭代
float2 zNew;
zNew.x = z.x * z.x - z.y * z.y + c.x;
zNew.y = 2.0 * z.x * z.y + c.y;
z = zNew;
// 检查发散条件
if (z.x * z.x + z.y * z.y > 4.0) {
iter = i;
break;
}
// 如果接近最大值,使用完整迭代计数
if (i == maxIter - 1.0) {
iter = maxIter;
}
}
// 使用switch进行颜色分类(模拟,Cg可能不支持switch)
float colorClass = 0.0;
if (iter < 5.0) {
colorClass = 0.1;
}
else if (iter < 10.0) {
colorClass = 0.3;
}
else if (iter < 15.0) {
colorClass = 0.5;
}
else if (iter < maxIter) {
colorClass = 0.7;
}
else {
colorClass = 0.9;
}
result = colorClass;
}
OUT.controlFlowMask = result;
return OUT;
}
)";
const char* fragmentShader = R"(
// Cg控制流语句演示 - 片段着色器
struct FragmentInput {
float2 texcoord : TEXCOORD0;
float controlFlowMask : TEXCOORD1;
};
struct FragmentOutput {
float4 color : COLOR;
};
uniform int renderTechnique;
// 颜色映射函数
float3 valueToColor(float value)
{
float3 color;
if (value < 0.2) {
color = lerp(float3(0.0, 0.0, 0.0), float3(0.0, 0.0, 1.0), value * 5.0);
}
else if (value < 0.4) {
color = lerp(float3(0.0, 0.0, 1.0), float3(0.0, 1.0, 1.0), (value - 0.2) * 5.0);
}
else if (value < 0.6) {
color = lerp(float3(0.0, 1.0, 1.0), float3(0.0, 1.0, 0.0), (value - 0.4) * 5.0);
}
else if (value < 0.8) {
color = lerp(float3(0.0, 1.0, 0.0), float3(1.0, 1.0, 0.0), (value - 0.6) * 5.0);
}
else {
color = lerp(float3(1.0, 1.0, 0.0), float3(1.0, 0.0, 0.0), (value - 0.8) * 5.0);
}
return color;
}
FragmentOutput main(FragmentInput IN)
{
FragmentOutput OUT;
float2 uv = IN.texcoord;
if (renderTechnique == 0) {
// 直接使用顶点着色器的结果
float3 color = valueToColor(IN.controlFlowMask);
OUT.color = float4(color, 1.0);
}
else {
// 在片段着色器中应用复杂控制流
float finalValue = 0.0;
// 多层条件系统
if (uv.x < 0.5 && uv.y < 0.5) {
// 左下象限:同心圆
float2 center = float2(0.25, 0.25);
float dist = distance(uv, center);
for (int i = 1; i <= 3; i++) {
float radius = i * 0.1;
if (dist < radius) {
finalValue = i * 0.1;
break;
}
}
}
else if (uv.x >= 0.5 && uv.y < 0.5) {
// 右下象限:水平条纹
int stripeCount = 6;
for (int i = 0; i < stripeCount; i++) {
float stripePos = float(i) / float(stripeCount);
if (uv.y > stripePos && uv.y < stripePos + 0.08) {
finalValue = 0.3 + (i % 2) * 0.4;
break;
}
}
}
else if (uv.x < 0.5 && uv.y >= 0.5) {
// 左上象限:垂直条纹
int stripeCount = 5;
int hitStripe = -1;
for (int i = 0; i < stripeCount; i++) {
float stripePos = float(i) / float(stripeCount);
if (uv.x > stripePos && uv.x < stripePos + 0.1) {
hitStripe = i;
break;
}
}
if (hitStripe != -1) {
finalValue = 0.2 + (hitStripe * 0.15);
}
}
else {
// 右上象限:复杂模式
float2 gridUV = uv * 4.0;
float2 gridPos = frac(gridUV);
int2 cell = int2(floor(gridUV));
float cellValue = 0.0;
int maxChecks = 4;
int checksDone = 0;
while (checksDone < maxChecks) {
// 基于单元格位置的模式
if ((cell.x + cell.y) % 2 == 0) {
if (gridPos.x > 0.3 && gridPos.y > 0.3) {
cellValue = 0.8;
break;
}
}
else {
if (gridPos.x < 0.7 || gridPos.y < 0.7) {
cellValue = 0.4;
break;
}
}
// 尝试其他条件
if (length(gridPos - 0.5) < 0.2) {
cellValue = 0.6;
break;
}
checksDone++;
}
finalValue = cellValue;
}
float3 color = valueToColor(finalValue);
OUT.color = float4(color, 1.0);
}
return OUT;
}
)";
vertexProgram = cgCreateProgram(context, CG_SOURCE, vertexShader,
vertexProfile, "main", nullptr);
if (!vertexProgram) return false;
cgGLLoadProgram(vertexProgram);
fragmentProgram = cgCreateProgram(context, CG_SOURCE, fragmentShader,
fragmentProfile, "main", nullptr);
if (!fragmentProgram) return false;
cgGLLoadProgram(fragmentProgram);
std::cout << "控制流语句着色器编译成功!" << std::endl;
return true;
}
void setControlFlowParameters(float time, int flowPattern, int renderTechnique) {
CGparameter param = cgGetNamedParameter(vertexProgram, "time");
cgSetParameter1f(param, time);
param = cgGetNamedParameter(vertexProgram, "flowPattern");
cgSetParameter1f(param, (float)flowPattern);
param = cgGetNamedParameter(fragmentProgram, "renderTechnique");
cgSetParameter1f(param, (float)renderTechnique);
}
void enableShaders() {
cgGLEnableProfile(vertexProfile);
cgGLEnableProfile(fragmentProfile);
cgGLBindProgram(vertexProgram);
cgGLBindProgram(fragmentProgram);
}
void disableShaders() {
cgGLDisableProfile(vertexProfile);
cgGLDisableProfile(fragmentProfile);
}
};
int main() {
glfwInit();
GLFWwindow* window = glfwCreateWindow(800, 600, "Cg控制流语句演示", NULL, NULL);
glfwMakeContextCurrent(window);
glewInit();
std::cout << "=== Cg控制流语句演示 ===" << std::endl;
std::cout << "控制流模式:" << std::endl;
std::cout << "1: if-else | 2: for循环 | 3: while循环 | 4: 复杂控制流" << std::endl;
std::cout << "渲染技术:" << std::endl;
std::cout << "Q: 顶点结果 | W: 片段计算" << std::endl;
ControlFlowDemo flowDemo;
if (!flowDemo.compileControlFlowShaders()) {
std::cerr << "着色器编译失败" << std::endl;
return -1;
}
int flowPattern = 0;
int renderTech = 0;
// 创建全屏四边形
unsigned int VAO, VBO;
float quadVertices[] = {
-1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
-1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
-1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
1.0f, 1.0f, 0.0f, 1.0f, 1.0f
};
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), quadVertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
// 主循环
while (!glfwWindowShouldClose(window)) {
glClear(GL_COLOR_BUFFER_BIT);
// 处理按键输入
if (glfwGetKey(window, GLFW_KEY_1) == GLFW_PRESS) flowPattern = 0;
if (glfwGetKey(window, GLFW_KEY_2) == GLFW_PRESS) flowPattern = 1;
if (glfwGetKey(window, GLFW_KEY_3) == GLFW_PRESS) flowPattern = 2;
if (glfwGetKey(window, GLFW_KEY_4) == GLFW_PRESS) flowPattern = 3;
if (glfwGetKey(window, GLFW_KEY_Q) == GLFW_PRESS) renderTech = 0;
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) renderTech = 1;
flowDemo.setControlFlowParameters((float)glfwGetTime(), flowPattern, renderTech);
flowDemo.enableShaders();
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 6);
flowDemo.disableShaders();
glfwSwapBuffers(window);
glfwPollEvents();
}
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glfwTerminate();
return 0;
}
代码解释:这个程序全面演示了Cg控制流语句的各种应用。包括if-else条件分支、for循环创建网格模式、while循环实现光线步进,以及复杂的控制流组合。特别展示了在片段着色器中使用控制流创建复杂图案的技术,包括象限分割、条纹模式和网格计算等高级应用。
6.7 本章核心要点总结
通过本章的学习,我们深入掌握了Cg语言操作符和控制流语句的各个方面:
操作符系统:
- 关系操作符用于比较运算,支持标量和向量
- 逻辑操作符构建复杂条件,支持短路求值
- 数学操作符提供基础计算能力,支持向量运算
- 移位操作符用于位操作,在某些场景下优化性能
- Swizzle操作符是Cg特色功能,极大简化向量操作
- 条件操作符提供紧凑的条件赋值语法
控制流语句:
- if-else语句实现条件分支
- 循环语句(for、while)处理重复任务
- 控制转移语句(break、continue)优化循环逻辑
关键实践要点:
- 理解操作符优先级,使用括号明确复杂表达式意图
- 合理使用控制流,避免在性能敏感区域使用复杂分支
- 利用Swizzle操作符简化向量操作,提高代码可读性
- 注意不同Profile对操作符和控制流的支持差异
所有代码实例都经过精心设计,在VSCODE和VS2022环境中可正确运行。通过这些实例,我们不仅学习了Cg操作符和控制流的技术细节,还掌握了如何在实际项目中应用这些知识来创建高效、可维护的着色器代码。
Cg语言的操作符和控制流系统虽然现在较少在新项目中使用,但其设计理念对现代着色器语言仍有重要影响。理解这些概念有助于我们更好地掌握图形编程的本质,为学习现代图形API打下坚实基础。
浙公网安备 33010602011771号