gpt4 book ai didi

opengl - 纹理颜色显示不正确

转载 作者:行者123 更新时间:2023-12-01 11:06:13 26 4
gpt4 key购买 nike

这是关于 OpenGL 中光照和纹理的基本问题。我尝试在纯 OpenGL 应用程序中应用纹理,不幸的是,颜色与纹理不同。这是纹理:

texture screenshot

这是我应用纹理后得到的:

textured teapot

我用了Videotutorialrocks BMP 装载机。如果我使用他们的 BMP 文件(即颜色与纹理文件相同),则不存在此着色问题。

代码如下:

#include <windows.h>
#include <GL/glut.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <sstream>
#include <iomanip>
#include "imageloader.h"

using std::stringstream;
using std::cout;
using std::endl;
using std::ends;

using namespace std;

float lpos[4] = {1.0,0.0,0.0,0.0};
void *font = GLUT_BITMAP_8_BY_13;
float color[4] = {0.0, 1.0, 0.0, 1.0};
GLuint _textureId; //The id of the texture
float a = 0;
float eye_x = 5.0;
float eye_y = 5.0;
float eye_z = 5.0;

//Makes the image into a texture, and returns the id of the texture
GLuint loadTexture(Image* image) {
GLuint textureId;
glGenTextures(1, &textureId); //Make room for our texture
glBindTexture(GL_TEXTURE_2D, textureId); //Tell OpenGL which texture to edit
//Map the image to the texture
glTexImage2D(GL_TEXTURE_2D, //Always GL_TEXTURE_2D
0, //0 for now
GL_RGB, //Format OpenGL uses for image
image->width, image->height, //Width and height
0, //The border of the image
GL_RGB, //GL_RGB, because pixels are stored in RGB format
GL_UNSIGNED_BYTE, //GL_UNSIGNED_BYTE, because pixels are stored
//as unsigned numbers
image->pixels); //The actual pixel data
return textureId; //Returns the id of the texture
}


// write 2d text using GLUT
// The projection matrix must be set to orthogonal before call this function.
void drawString(const char *str, int x, int y, float color[4], void *font)
{
glPushAttrib(GL_LIGHTING_BIT | GL_CURRENT_BIT); // lighting and color mask
glDisable(GL_LIGHTING); // need to disable lighting for proper text color
glColor4fv(color); // set text color
glRasterPos2i(x, y); // place text position

// loop all characters in the string
while(*str)
{
glutBitmapCharacter(font, *str);
++str;
}

glEnable(GL_LIGHTING);
glPopAttrib();
}

void changeSize(int w, int h) {

// Prevent a divide by zero, when window is too short. (you cant make a window of zero width).
if(h == 0)
h = 1;

float ratio = 1.0* w / h;

// Reset the coordinate system before modifying
glMatrixMode(GL_PROJECTION);
glLoadIdentity();

// Set the viewport to be the entire window
glViewport(0, 0, w, h);

// Set the correct perspective.
gluPerspective(45,ratio,1,100);
glMatrixMode(GL_MODELVIEW);
}

void initRendering(){
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHT1);
glEnable(GL_NORMALIZE);
glEnable(GL_COLOR_MATERIAL);
Image* image = loadBMP("vtr_6.bmp");
_textureId = loadTexture(image);
delete image;

}

void renderScene(void) {

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

//Add ambient light
//GLfloat ambientColor[] = {0.4f, 0.2f, 0.2f, 1.0f}; //Color(0.2, 0.2, 0.2)
GLfloat ambientColor[] = {1.0f, 1.0f, 1.0f, 1.0f}; //Color(0.2, 0.2, 0.2)
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambientColor);

//Add positioned light
//GLfloat lightColor0[] = {0.5f, 0.5f, 0.5f, 1.0f}; //Color (0.5, 0.5, 0.5)
GLfloat lightColor0[] = {1.0f, 1.0f, 1.0f, 1.0f}; //Color (0.5, 0.5, 0.5)
GLfloat lightPos0[] = {4.0f, 0.0f, 8.0f, 1.0f}; //Positioned at (4, 0, 8)
glLightfv(GL_LIGHT0, GL_DIFFUSE, lightColor0);
glLightfv(GL_LIGHT0, GL_POSITION, lightPos0);

//Add directed light
//GLfloat lightColor1[] = {0.7f, 0.2f, 0.1f, 1.0f}; //Color (0.5, 0.2, 0.2)
GLfloat lightColor1[] = {1.0f, 1.0f, 1.0f, 1.0f};
//Coming from the direction (-1, 0.5, 0.5)
GLfloat lightPos1[] = {1.0f, 0.5f, 0.5f, 0.0f};
glLightfv(GL_LIGHT1, GL_DIFFUSE, lightColor1);
glLightfv(GL_LIGHT1, GL_POSITION, lightPos1);

glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, _textureId);
//Bottom
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

gluLookAt(eye_x,eye_y,eye_z,
0.0,0.0,0.0,
0.0f,1.0f,0.0f);

stringstream ss;
ss << std::fixed << std::setprecision(2);

ss << "Eye Position : x,y,z = (" << eye_x << ", " << eye_y << ", " << eye_z << ")" << ends;
drawString(ss.str().c_str(), -6, 1, color, font);
ss.str("");

glRotatef(a,0,1,0);
glutSolidTeapot(2);
glDisable(GL_TEXTURE_2D);
a+=0.1;

glutSwapBuffers();
}



void processNormalKeys(unsigned char key, int x, int y) {
switch ( key )
{
case 27:
exit(0);
break;
case '1':
eye_x += 0.1;
break;
case '2':
eye_x -= 0.1;
break;
case '3' :
eye_y += 0.1;
break;
case '4' :
eye_y -= 0.1;
break;
case '5':
eye_z += 0.1;;
break;
case '6':
eye_z -= 0.1;
break;
case '0':
eye_x = 5.0;
eye_y = 5.0;
eye_z = 5.0;
break;
}
}

#define printOpenGLError() printOglError(__FILE__, __LINE__)

int printOglError(char *file, int line)
{
GLenum glErr;
int retCode = 0;

glErr = glGetError();
while (glErr != GL_NO_ERROR)
{
printf("glError in file %s @ line %d: %s\n", file, line, gluErrorString(glErr));
retCode = 1;
glErr = glGetError();
}
return retCode;
}


int main(int argc, char **argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowPosition(100,100);
glutInitWindowSize(800,600);
glutCreateWindow("OpenGL Teapot w/ lighting");
initRendering();
glutDisplayFunc(renderScene);

glutReshapeFunc(changeSize);
glutKeyboardFunc(processNormalKeys);

glutIdleFunc(renderScene);

glEnable(GL_DEPTH_TEST);
glClearColor(0.0,0.0,0.0,0.0);

glutMainLoop();
return 0;
}

这是图像加载器的代码:

    #include <assert.h>
#include <fstream>

#include "imageloader.h"

using namespace std;

Image::Image(char* ps, int w, int h) : pixels(ps), width(w), height(h) {

}

Image::~Image() {
delete[] pixels;
}

namespace {
//Converts a four-character array to an integer, using little-endian form
int toInt(const char* bytes) {
return (int)(((unsigned char)bytes[3] << 24) |
((unsigned char)bytes[2] << 16) |
((unsigned char)bytes[1] << 8) |
(unsigned char)bytes[0]);
}

//Converts a two-character array to a short, using little-endian form
short toShort(const char* bytes) {
return (short)(((unsigned char)bytes[1] << 8) |
(unsigned char)bytes[0]);
}

//Reads the next four bytes as an integer, using little-endian form
int readInt(ifstream &input) {
char buffer[4];
input.read(buffer, 4);
return toInt(buffer);
}

//Reads the next two bytes as a short, using little-endian form
short readShort(ifstream &input) {
char buffer[2];
input.read(buffer, 2);
return toShort(buffer);
}

//Just like auto_ptr, but for arrays
template<class T>
class auto_array {
private:
T* array;
mutable bool isReleased;
public:
explicit auto_array(T* array_ = NULL) :
array(array_), isReleased(false) {
}

auto_array(const auto_array<T> &aarray) {
array = aarray.array;
isReleased = aarray.isReleased;
aarray.isReleased = true;
}

~auto_array() {
if (!isReleased && array != NULL) {
delete[] array;
}
}

T* get() const {
return array;
}

T &operator*() const {
return *array;
}

void operator=(const auto_array<T> &aarray) {
if (!isReleased && array != NULL) {
delete[] array;
}
array = aarray.array;
isReleased = aarray.isReleased;
aarray.isReleased = true;
}

T* operator->() const {
return array;
}

T* release() {
isReleased = true;
return array;
}

void reset(T* array_ = NULL) {
if (!isReleased && array != NULL) {
delete[] array;
}
array = array_;
}

T* operator+(int i) {
return array + i;
}

T &operator[](int i) {
return array[i];
}
};
}

Image* loadBMP(const char* filename) {
ifstream input;
input.open(filename, ifstream::binary);
assert(!input.fail() || !"Could not find file");
char buffer[2];
input.read(buffer, 2);
assert(buffer[0] == 'B' && buffer[1] == 'M' || !"Not a bitmap file");
input.ignore(8);
int dataOffset = readInt(input);

//Read the header
int headerSize = readInt(input);
int width;
int height;
switch(headerSize) {
case 40:
//V3
width = readInt(input);
height = readInt(input);
input.ignore(2);
assert(readShort(input) == 24 || !"Image is not 24 bits per pixel");
assert(readShort(input) == 0 || !"Image is compressed");
break;
case 12:
//OS/2 V1
width = readShort(input);
height = readShort(input);
input.ignore(2);
assert(readShort(input) == 24 || !"Image is not 24 bits per pixel");
break;
case 64:
//OS/2 V2
assert(!"Can't load OS/2 V2 bitmaps");
break;
case 108:
//Windows V4
assert(!"Can't load Windows V4 bitmaps");
break;
case 124:
//Windows V5
assert(!"Can't load Windows V5 bitmaps");
break;
default:
assert(!"Unknown bitmap format");
}

//Read the data
int bytesPerRow = ((width * 3 + 3) / 4) * 4 - (width * 3 % 4);
int size = bytesPerRow * height;
auto_array<char> pixels(new char[size]);
input.seekg(dataOffset, ios_base::beg);
input.read(pixels.get(), size);

//Get the data into the right format
auto_array<char> pixels2(new char[width * height * 3]);
for(int y = 0; y < height; y++) {
for(int x = 0; x < width; x++) {
for(int c = 0; c < 3; c++) {
pixels2[3 * (width * y + x) + c] =
pixels[bytesPerRow * y + 3 * x + (2 - c)];
}
}
}

input.close();
return new Image(pixels2.release(), width, height);
}

这是头文件:

#ifndef IMAGE_LOADER_H_INCLUDED
#define IMAGE_LOADER_H_INCLUDED

//Represents an image
class Image {
public:
Image(char* ps, int w, int h);
~Image();

/* An array of the form (R1, G1, B1, R2, G2, B2, ...) indicating the
* color of each pixel in image. Color components range from 0 to 255.
* The array starts the bottom-left pixel, then moves right to the end
* of the row, then moves up to the next column, and so on. This is the
* format in which OpenGL likes images.
*/
char* pixels;
int width;
int height;
};

//Reads a bitmap image from file.
Image* loadBMP(const char* filename);
#endif

我已尝试替换 glTexImage2D 的文件格式使用 GL_BGR_EXT,但没有结果。有什么办法可以修正纹理吗?

最佳答案

也许您的图像有一个 alpha channel ,它需要 GL_RGBA,而不是 GL_RGB。

关于opengl - 纹理颜色显示不正确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5674512/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com