openGL之API学习(二零四)GL_TEXTURE_MIN_FILTER GL_TEXTURE_MAG_FILTER

本文介绍了OpenGL中纹理过滤的两种模式——GL_TEXTURE_MIN_FILTER和GL_TEXTURE_MAG_FILTER的使用,包括其取值和默认设置。GL_TEXTURE_MIN_FILTER用于控制纹理缩小时的过滤方式,而GL_TEXTURE_MAG_FILTER则决定了纹理放大的效果。GL_NEAREST产生更锐利的边缘但速度较快,GL_LINEAR则提供更平滑的过渡但计算量稍大。示例代码展示了如何设置这两种过滤方式为GL_LINEAR。
部署运行你感兴趣的模型镜像

设置纹理过滤方式。

1、GL_TEXTURE_MIN_FILTER

GL_TEXTURE_MIN_FILTER取值GL_NEAREST GL_LINEAR GL_NEAREST_MIPMAP_NEAREST GL_LINEAR_MIPMAP_NEAREST GL_NEAREST_MIPMAP_LINEAR GL_LINEAR_MIPMAP_LINEAR,默认GL_NEAREST_MIPMAP_LINEA

2、GL_TEXTURE_MAG_FILTER

GL_TEXTURE_MAG_FILTER取值GL_NEAREST GL_LINEAR,默认GL_LINEAR。

当从纹理采样时使用的“细节级别”功能确定纹理应该被成像时,就会使用“纹理放大”功能。它将纹理放大功能设置为GL_NEAREST或GL_LINEAR。GL_NEAREST通常比GL_LINEAR更快,但它可以生成边缘更锐利的纹理图像,因为纹理元素之间的过渡没有那么平滑。GL_纹理_MAG_过滤器的初始值为GL_线性。

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

您可能感兴趣的与本文相关的镜像

Kotaemon

Kotaemon

AI应用

Kotaemon 是由Cinnamon 开发的开源项目,是一个RAG UI页面,主要面向DocQA的终端用户和构建自己RAG pipeline

那就用soil2来解决运行没有纹理图片G:\Demo3\Demo3\textures,container.jpg,wood.png,// Cube18.h #ifndef CUBE18_H #define CUBE18_H #include <string> // ✅ 必须添加!解决 std::string 报错 #include <glad/glad.h> class Cube18 { public: // 构造函数:接收顶点和片段着色器路径 Cube18(const std::string& vertexPath, const std::string& fragmentPath); // 析构函数 ~Cube18(); // 初始化立方体数据(VBO/VAO/EBO) void init(); // 渲染立方体,传入窗口宽高用于投影矩阵 void render(float width, float height); // 更新逻辑(可用于动画) void update(float dt); private: unsigned int VAO, VBO, EBO; unsigned int shaderProgram; float rotationAngle = 0.0f; // 私有辅助函数:创建着色器程序 unsigned int createShaderProgram(const std::string& vsPath, const std::string& fsPath); }; #endif // CUBE18_H // Cube18.cpp #include "Cube18.h" #include <glad/glad.h> #include <GLFW/glfw3.h> #include <glm/glm.hpp> #include <glm/gtc/matrix_transform.hpp> #include <iostream> #include <fstream> #include <sstream> #include <glm/gtc/type_ptr.hpp> #include <string> // 显式包含(虽然通常被其他头文件带入) // 外部纹理变量(需在 main.cpp 中定义) extern unsigned int texWood; extern unsigned int texContainer; // 辅助函数:读取着色器文件 std::string readShaderFile(const std::string& path) { std::ifstream file(path); if (!file.is_open()) { std::cerr << "无法打开着色器文件: " << path << std::endl; return ""; } std::stringstream buffer; buffer << file.rdbuf(); return buffer.str(); } // 创建着色器程序(私有方法) unsigned int Cube18::createShaderProgram(const std::string& vsPath, const std::string& fsPath) { std::string vsCodeStr = readShaderFile(vsPath); std::string fsCodeStr = readShaderFile(fsPath); const char* vertexCode = vsCodeStr.c_str(); const char* fragmentCode = fsCodeStr.c_str(); // 编译顶点着色器 unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vertexShader, 1, &vertexCode, nullptr); glCompileShader(vertexShader); int success; char infoLog[512]; glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success); if (!success) { glGetShaderInfoLog(vertexShader, 512, NULL, infoLog); std::cerr << "顶点着色器编译失败:\n" << infoLog << std::endl; } // 编译片段着色器 unsigned int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fragmentShader, 1, &fragmentCode, nullptr); glCompileShader(fragmentShader); glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success); if (!success) { glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog); std::cerr << "片段着色器编译失败:\n" << infoLog << std::endl; } // 链接程序 unsigned int program = glCreateProgram(); glAttachShader(program, vertexShader); glAttachShader(program, fragmentShader); glLinkProgram(program); glGetProgramiv(program, GL_LINK_STATUS, &success); if (!success) { glGetProgramInfoLog(program, 512, NULL, infoLog); std::cerr << "着色器程序链接失败:\n" << infoLog << std::endl; } glDeleteShader(vertexShader); glDeleteShader(fragmentShader); return program; } // 构造函数 Cube18::Cube18(const std::string& vertexPath, const std::string& fragmentPath) : shaderProgram(createShaderProgram(vertexPath, fragmentPath)) {} // 析构函数 Cube18::~Cube18() { glDeleteVertexArrays(1, &VAO); glDeleteBuffers(1, &VBO); glDeleteBuffers(1, &EBO); glDeleteProgram(shaderProgram); } // 初始化顶点数据 void Cube18::init() { float vertices[] = { 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, -0.5f, -0.5f, 0.5f, 0.0f, 1.0f, 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.5f, -0.5f, 0.5f, 1.0f, 1.0f, -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.5f, -0.5f, -0.5f, 1.0f, 1.0f, -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.5f, -0.5f, -0.5f, 1.0f, 1.0f, -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, -0.5f, 0.5f, -0.5f, 0.0f, 0.0f }; unsigned int indices[] = { 0, 1, 3, 0, 3, 2, 4, 5, 7, 4, 7, 6, 8, 9, 11, 8, 11, 10, 2, 3, 9, 2, 9, 5, 0, 7, 11, 0, 11, 1, 5, 7, 13, 5, 13, 12 }; glGenVertexArrays(1, &VAO); glGenBuffers(1, &VBO); glGenBuffers(1, &EBO); glBindVertexArray(VAO); glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0); glEnableVertexAttribArray(0); glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float))); glEnableVertexAttribArray(2); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0); } // 渲染函数 void Cube18::render(float width, float height) { glUseProgram(shaderProgram); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, texWood); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, texContainer); unsigned int modelLoc = glGetUniformLocation(shaderProgram, "model"); unsigned int viewLoc = glGetUniformLocation(shaderProgram, "view"); unsigned int projLoc = glGetUniformLocation(shaderProgram, "projection"); glm::mat4 model = glm::mat4(1.0f); glm::vec3 cameraPos = glm::vec3(0.0f, 0.0f, 3.0f); glm::vec3 target = glm::vec3(0.0f, 0.0f, 0.0f); glm::vec3 up = glm::vec3(0.0f, 1.0f, 0.0f); glm::mat4 view = glm::lookAt(cameraPos, target, up); float aspect = width / height; glm::mat4 projection = glm::perspective(glm::radians(45.0f), aspect, 0.1f, 100.0f); float time = glfwGetTime(); model = glm::rotate(model, time * 0.5f, glm::vec3(1.0f, 1.0f, 0.0f)); glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model)); glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view)); glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection)); glUniform1i(glGetUniformLocation(shaderProgram, "texture1"), 0); glUniform1i(glGetUniformLocation(shaderProgram, "texture2"), 1); glBindVertexArray(VAO); glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0); glBindVertexArray(0); } // 更新函数 void Cube18::update(float dt) { rotationAngle += dt * 0.5f; } #include <glad/glad.h> #include <GLFW/glfw3.h> #include <iostream> #include "Lab3_2.h" #include "Demo3_2.h" #include "Demo3_3.h" #include"Hexagon.h" #include"ColorTriangle.h" #include"ColorHexagon.h" #include "WaveHexagon.h" #include "Cube18.h" // 👈 新增:包含 Cube18 头文件 using namespace std; unsigned int texWood; unsigned int texContainer; // settings const unsigned int SCR_WIDTH = 1200; const unsigned int SCR_HEIGHT = 800; GLFWwindow* window; void framebuffer_size_callback(GLFWwindow* window, int width, int height); void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods); void processInput(GLFWwindow* window); void render(); void init(); void cleanup(); Lab3_2* lab3_2 = nullptr; //指向 Lab3_2 实例的指针,用于管理第一个实验场景(例如带面剔除功能的三角形渲染),初始化为空,防止野指针 Demo3_2* demo3_2 = nullptr; Demo3_3* demo3_3 = nullptr; Hexagon* hexagon = nullptr; ColorTriangle* colorTriangle = nullptr; ColorHexagon* colorHexagon = nullptr; WaveHexagon* waveHexagon = nullptr; Cube18* cube18 = nullptr; int sceneType = 1; // 当前激活的场景编号:1 -> Lab3_2, 2 -> Demo3_2, 3 -> Demo3_3,可通过键盘按键切换不同场景 bool enableCullFace = false; // 是否启用面剔除(Face Culling)的状态标志,控制是否调用 glEnable(GL_CULL_FACE) GLenum cullMode = GL_FRONT; //当前面剔除模式:默认剔除正面(GL_FRONT)可选值:GL_BACK(剔除背面)、GL_FRONT_AND_BACK(都剔除) GLenum frontFace = GL_CCW; //正面判定方式:逆时针方向为正面(Counter-Clockwise),对应 glFrontFace 的参数,影响哪些面被认为是“正面” int main() { //初始化glfw窗口 glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);//上下文版本号 glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // 创建窗口对象 window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "Demo3", NULL, NULL); if (window == NULL) //窗口创建失败提示 { std::cout << "Failed to create GLFW window" << std::endl; glfwTerminate(); return -1; } glfwMakeContextCurrent(window); // 将 OpenGL 上下文设置为当前线程的主上下文,所有 OpenGL 调用都将作用于该窗口 glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); //注册帧缓冲大小变化的回调函数.当窗口被缩放或最大化时,会自动调整视口大小 glfwSetKeyCallback(window, key_callback); // 注册键盘按键事件的回调函数,每当有键按下/释放时触发 key_callback初始化glad if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))//glad初始化检查 { std::cout << "Failed to initialize GLAD" << std::endl; return -1; } int nrAttributes; glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &nrAttributes); //查询 OpenGL 支持的最大顶点属性数量 std::cout << "Maximum nr of vertex attributes supported: " << nrAttributes << std::endl; init(); // 窗口消息循环 while (!glfwWindowShouldClose(window)) { processInput(window); // 输入 render(); // 渲染 glfwSwapBuffers(window); //交换前后缓冲区,实现双缓冲机制,防止画面撕裂 glfwPollEvents(); } cleanup(); //释放内存 glfwTerminate(); //终止 GLFW,清理所有相关资源 return 0; } void cleanup() { if (lab3_2) { delete lab3_2; } if (demo3_2) { delete demo3_2; } if (demo3_3) { delete demo3_3; } if (hexagon) { delete hexagon; } if (colorTriangle) { delete colorTriangle; } if (colorHexagon) { delete colorHexagon; } if (waveHexagon) { delete waveHexagon; waveHexagon = nullptr; } if (cube18) { delete cube18; } } void init() { lab3_2 = new Lab3_2(); lab3_2->setRenderParameter(); //设置其初始渲染参数(如面剔除状态) demo3_2 = new Demo3_2(); demo3_2->setRenderParameter(); demo3_3 = new Demo3_3(); demo3_3->setRenderParameter(); hexagon = new Hexagon(); hexagon->initData(); // 初始化六边形,显式初始化六边形的顶点缓冲区和 VAO/VBO。 colorTriangle = new ColorTriangle(); colorHexagon = new ColorHexagon(); colorHexagon->initData(); // 在 init() 或主函数开始处 waveHexagon = new WaveHexagon(); waveHexagon->init(); cube18 = new Cube18("shaders/Cube.vs", "shaders/Cube.fs"); cube18->init(); glGenTextures(1, &texWood); glBindTexture(GL_TEXTURE_2D, texWood); unsigned char white[] = { 255, 255, 255 }; glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, white); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glGenTextures(1, &texContainer); glBindTexture(GL_TEXTURE_2D, texContainer); unsigned char yellow[] = { 255, 255, 0 }; glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, yellow); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } void render() { glClearColor(0.2, 0.3, 0.2, 1); //设置清除颜色为深绿色 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // ✅ 加上深度清除 //清除颜色缓冲区,准备新一帧绘制 if (sceneType == 1 && lab3_2) //判断当前应激活的场景是否为 Lab3_2 场景,并确保该场景对象已成功创建 { lab3_2->render(); } else if (sceneType == 2 && demo3_2) { demo3_2->render(); } else if (sceneType == 3 && demo3_3) { demo3_3->render(); } else if (sceneType == 4 && hexagon) { hexagon->renderObject(); // 渲染六边形 } else if (sceneType == 5 && colorTriangle) { colorTriangle->render(); } else if (sceneType == 6 && colorHexagon) { colorHexagon->renderObject(); } else if (sceneType == 7 && waveHexagon) { waveHexagon->render(); } else if (sceneType == 8 && cube18) { std::cout << "[DEBUG] 正在渲染 Cube18 场景!\n"; glEnable(GL_DEPTH_TEST); // ✅ 开启深度测试 cube18->render(SCR_WIDTH, SCR_HEIGHT); // ✅ 传参 glDisable(GL_DEPTH_TEST); // 可选关闭 } } void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) { // 判断按键是否被释放 if (action == GLFW_RELEASE) //GLFW_RELEASE与GLFW_PRESS的区别 { if (key == GLFW_KEY_1)//释放的是数字键 1,则将当前场景切换为 Lab3_2(编号为 1) sceneType = 1; else if (key == GLFW_KEY_2) sceneType = 2; else if (key == GLFW_KEY_3) sceneType = 3; else if (key == GLFW_KEY_4) sceneType = 4; else if (key == GLFW_KEY_5) sceneType = 5; else if (key == GLFW_KEY_6) sceneType = 6; else if (key == GLFW_KEY_7) sceneType = 7; else if (key == GLFW_KEY_E) { enableCullFace = !enableCullFace; //切换面剔除开关状态 if (sceneType == 1 && lab3_2) { lab3_2->setRenderParameter(enableCullFace, cullMode, frontFace); } } else if (key == GLFW_KEY_C) //按C键切换绕向 { if (frontFace == GL_CCW) //如果当前为绕向为逆时针 { frontFace=GL_CW; //切换为顺时针 } else { frontFace = GL_CCW; } if (sceneType == 1 && lab3_2) { lab3_2->setRenderParameter(enableCullFace, cullMode, frontFace); } } else if (key == GLFW_KEY_F) //按键F切换裁剪面 { if (cullMode == GL_FRONT) //如果当前正面为裁剪面 { cullMode = GL_BACK; //切换成背面 } else { cullMode = GL_FRONT; } if (sceneType == 1 && lab3_2) { lab3_2->setRenderParameter(enableCullFace, cullMode, frontFace); } } else if (key == GLFW_KEY_8) { sceneType = 8; } } } void processInput(GLFWwindow* window) //处理每帧的输入(主要用于连续按键检测) { if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) glfwSetWindowShouldClose(window, true); } // 窗口回调函数 void framebuffer_size_callback(GLFWwindow* window, int width, int height) { glViewport(0, 0, width, height); //设置 OpenGL 视口与窗口一致,参数:x, y, 宽度, 高度 }
最新发布
10-24
明白了!你不想使用 `stb_image.h` 来加载纹理,可能是出于以下原因: - 不想引入外部依赖 - 希望使用系统自带方式(如 SOIL、FreeImage)或硬编码颜色 - 项目限制不允许使用第三方库 --- ## ✅ 解决方案:**用纯色或程序化纹理替代 `stb_image.h`** 我们可以通过 **在片段着色器中生成颜色** 或 **上传简单的像素数组作为纹理** 来避免使用 `stb_image.h`。 --- ### ✅ 方案一:使用程序化纹理(推荐,零依赖) 我们将创建两个简单的 2x2 像素的 RGB 纹理: - `texture1`: 蓝色木箱风格(蓝底白边) - `texture2`: 黄色笑脸风格(黄底黑眼嘴) #### 📄 修改 `Cube.cpp` 中的纹理加载部分(替换 `stbi_load`) ```cpp // 在 Cube18::initData() 函数中,删除 stb_image 相关代码,改为: // 创建一个 2x2 的简单纹理数据(RGBA 格式) unsigned char blueWood[4 * 4] = { 0, 0, 255, 255, // 蓝 255, 255, 255, 255, // 白 255, 255, 255, 255, // 白 0, 0, 255, 255 // 蓝 }; unsigned char yellowFace[4 * 4] = { 255, 255, 0, 255, // 黄 255, 255, 0, 255, // 黄 255, 255, 0, 255, // 黄 0, 0, 0, 255 // 黑(模拟眼睛嘴巴) }; ``` #### 🔧 上传为 OpenGL 纹理 ```cpp // 绑定并上传第一个纹理(蓝色木纹) glGenTextures(1, &texture1); glBindTexture(GL_TEXTURE_2D, texture1); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, blueWood); glGenerateMipmap(GL_TEXTURE_2D); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // 绑定并上传第二个纹理(黄色笑脸) glGenTextures(1, &texture2); glBindTexture(GL_TEXTURE_2D, texture2); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, yellowFace); glGenerateMipmap(GL_TEXTURE_2D); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // 解绑 glBindTexture(GL_TEXTURE_2D, 0); ``` > ✅ 完全不需要 `stb_image.h`! --- ### ✅ 方案二:只使用单一颜色(最简版) 如果你连纹理都不想处理,可以直接在着色器里用统一变量控制颜色。 #### 📄 片段着色器示例(Cube.fs) ```glsl #version 330 core out vec4 FragColor; uniform vec3 solidColor; uniform bool useSolidColor; void main() { if (useSolidColor) { FragColor = vec4(solidColor, 1.0); } else { // 正常纹理逻辑(可保留兼容性) discard; // 或留空 } } ``` #### 📄 在 `renderObject()` 中设置颜色: ```cpp shader->use(); shader->setBool("useSolidColor", true); shader->setVec3("solidColor", glm::vec3(1.0f, 0.5f, 0.3f)); // 橙色 ``` > 这样就可以渲染出一个纯色立方体,完全无需纹理和 `stb_image.h` --- ### ✅ 方案三:编译时条件屏蔽(优雅写法) 你可以通过宏来决定是否启用图像加载: ```cpp // #define USE_STB_IMAGE // 注释掉表示不使用 stb_image #ifdef USE_STB_IMAGE #include "stb_image.h" #endif ``` 然后: ```cpp void Cube18::loadTexture(unsigned int& texID, const char* path, bool isAlpha = false) { glGenTextures(1, &texID); glBindTexture(GL_TEXTURE_2D, texID); #ifdef USE_STB_IMAGE int width, height, nrChannels; unsigned char* data = stbi_load(path, &width, &height, &nrChannels, isAlpha ? 4 : 3); if (data) { glTexImage2D(GL_TEXTURE_2D, 0, isAlpha ? GL_RGBA : GL_RGB, width, height, 0, isAlpha ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE, data); glGenerateMipmap(GL_TEXTURE_2D); stbi_image_free(data); } else { std::cerr << "Failed to load texture: " << path << std::endl; // fallback 到默认纹理 uploadDefaultTexture(texID, isAlpha); } #else // 默认 fallback 纹理 uploadDefaultTexture(texID, isAlpha); #endif glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } ``` --- ## ✅ 最终建议:使用“最小可行纹理”方案 直接使用如下代码替换所有 `stb_image` 加载逻辑: ```cpp // 替换原来 stb_image 加载纹理的部分 unsigned char defaultTex[] = { 255, 0, 0, 255, // 红 0, 255, 0, 255, // 绿 0, 0, 255, 255, // 蓝 255, 255, 0, 255 // 黄 }; glGenTextures(1, &texture1); glBindTexture(GL_TEXTURE_2D, texture1); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, defaultTex); glGenerateMipmap(GL_TEXTURE_2D); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); ``` 这样你就能看到一个 **四色拼贴旋转立方体**,完美运行且无任何外部依赖! --- ✅ 总结:无需 `stb_image.h` 的三种方式 | 方案 | 说明 | 推荐度 | |------|------|--------| | ✅ 程序化小纹理(2x2 数组) | 手动定义像素,上传为纹理 | ⭐⭐⭐⭐☆ | | ✅ 单色渲染 | 着色器内设 `uniform vec3 color` | ⭐⭐⭐⭐⭐(最简) | | ✅ 编译宏控制 | 条件编译是否支持图片加载 | ⭐⭐⭐⭐☆(专业做法) | ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值