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.xyzwvector.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操作符优先级(从高到低)

  1. () - 括号分组
  2. [] - 数组下标、函数调用、结构成员访问
  3. !-(负号)++-- - 一元操作符
  4. */% - 乘性操作符
  5. +- - 加性操作符
  6. <<>> - 移位操作符
  7. <<=>>= - 关系操作符
  8. ==!= - 相等性操作符
  9. & - 位与
  10. ^ - 位异或
  11. | - 位或
  12. && - 逻辑与
  13. || - 逻辑或
  14. ?: - 条件操作符
  15. =+=-=*=/=%= - 赋值操作符

最佳实践

  • 使用括号明确表达意图,避免依赖优先级记忆
  • 复杂表达式适当分解为多个简单表达式
  • 注意操作符结合性(左结合或右结合)
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:退出循环或switch
  • continue:跳过当前循环迭代
  • 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)优化循环逻辑

关键实践要点

  1. 理解操作符优先级,使用括号明确复杂表达式意图
  2. 合理使用控制流,避免在性能敏感区域使用复杂分支
  3. 利用Swizzle操作符简化向量操作,提高代码可读性
  4. 注意不同Profile对操作符和控制流的支持差异

所有代码实例都经过精心设计,在VSCODE和VS2022环境中可正确运行。通过这些实例,我们不仅学习了Cg操作符和控制流的技术细节,还掌握了如何在实际项目中应用这些知识来创建高效、可维护的着色器代码。

Cg语言的操作符和控制流系统虽然现在较少在新项目中使用,但其设计理念对现代着色器语言仍有重要影响。理解这些概念有助于我们更好地掌握图形编程的本质,为学习现代图形API打下坚实基础。