Я не могу отобразить плитку идеально на четырехугольниках, под идеальным я имею в виду, что она будет отображать только пиксели определенной плитки в текстурном изображении и ничего более.
Редактировать: (немного обновил код)
Я сейчас сделал пример рабочего кода:
/*
Image of the bug: https://i.stack.imgur.com/Drb5U.png
edit: the bug seems to change on different gfx cards, but still visible one way or another!
*/
#pragma comment(lib, "opengl32.lib")
#pragma comment(lib, "Glu32.lib")
#include <windows.h>
#include <stdio.h>
#include <gl/glew.h>
#include <gl/gl.h>
HDC hDC = NULL;
HGLRC hRC = NULL;
HWND hWnd = NULL;
HINSTANCE hInstance;
bool active = 1;
int window_width = 640;
int window_height = 480;
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam){
switch(uMsg){
case WM_ACTIVATE: {
active = !HIWORD(wParam);
return 0;
}
case WM_CLOSE: {
exit(0);
return 0;
}
case WM_SIZE: {
window_width = LOWORD(lParam);
window_height = HIWORD(lParam);
return 0;
}
}
return DefWindowProc(hWnd,uMsg,wParam,lParam);
}
BOOL create_window(int width, int height){
GLuint PixelFormat;
WNDCLASS wc;
DWORD dwExStyle,dwStyle;
RECT WindowRect;
WindowRect.left = (long)0;
WindowRect.right = (long)width;
WindowRect.top = (long)0;
WindowRect.bottom = (long)height;
hInstance = GetModuleHandle(NULL);
wc.style = CS_HREDRAW|CS_VREDRAW|CS_OWNDC;
wc.lpfnWndProc = (WNDPROC)WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = NULL;
wc.hCursor = NULL;
wc.hbrBackground = NULL;
wc.lpszMenuName = NULL;
wc.lpszClassName = TEXT("test");
if(!RegisterClass(&wc)) return FALSE;
dwExStyle = WS_EX_APPWINDOW|WS_EX_WINDOWEDGE;
dwStyle = WS_OVERLAPPEDWINDOW;
ShowCursor(TRUE);
AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle);
if(!(hWnd = CreateWindowEx(dwExStyle,TEXT("test"),TEXT("test"),dwStyle|WS_CLIPSIBLINGS|WS_CLIPCHILDREN,0,0,width,height,NULL,NULL,hInstance,NULL))) return FALSE;
static PIXELFORMATDESCRIPTOR pfd = {sizeof(PIXELFORMATDESCRIPTOR),1,PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|PFD_DOUBLEBUFFER,PFD_TYPE_RGBA,(BYTE)32,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,PFD_MAIN_PLANE,0,0,0,0};
if(!(hDC = GetDC(hWnd))) return FALSE;
if(!(PixelFormat = ChoosePixelFormat(hDC, &pfd))) return FALSE;
if(!SetPixelFormat(hDC, PixelFormat, &pfd)) return FALSE;
if(!(hRC = wglCreateContext(hDC))) return FALSE;
if(!wglMakeCurrent(hDC, hRC)) return FALSE;
ShowWindow(hWnd, SW_SHOW);
SetForegroundWindow(hWnd);
SetFocus(hWnd);
return TRUE;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow){
if(!create_window(window_width,window_height)){
return 1;
}
glShadeModel(GL_SMOOTH);
glDisable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glClearColor(0,0,0,1);
glColor4f(1,1,1,1);
// create red/yellow checkers pattern with slightly randomized tile pixels:
int img_w = 256;
int img_h = 256;
int tilesize = 16;
unsigned int *data = (unsigned int *)malloc(img_w*img_h*4);
unsigned int colors[] = {0xFF3333, 0xFFFF33};
for(int y = 0; y < img_h; y+=tilesize){
for(int x = 0; x < img_w; x+=tilesize){
unsigned int i = ((x/tilesize)+((y/tilesize)%2))%2;
for(int yy = 0; yy < tilesize; yy++){
for(int xx = 0; xx < tilesize; xx++){
int r = ((colors[i]>>0)&255)-(rand()%30);
int g = ((colors[i]>>8)&255)-(rand()%30);
int b = ((colors[i]>>16)&255)-(rand()%30);
if(r < 0) r = 0;
if(g < 0) g = 0;
if(b < 0) b = 0;
data[(y+yy)*img_w+(x+xx)] = (b << 16) | (g << 8) | r;
}
}
}
}
// take one tile somewhere from middle and make texcoords for it:
int x = 2*tilesize;
int y = 4*tilesize;
float tx1 = (float)x/img_w;
float ty1 = (float)y/img_h;
float tx2 = (float)(x+tilesize)/img_w;
float ty2 = (float)(y+tilesize)/img_h;
unsigned int texid = 0;
glGenTextures(1, &texid);
glBindTexture(GL_TEXTURE_2D, texid);
glEnable(GL_TEXTURE_2D);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, img_w, img_h, 0, GL_BGRA, GL_UNSIGNED_BYTE, data);
free(data);
BOOL done = 0;
static MSG msg;
float zpos = 600.0f;
while(!done){
if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)){
if(msg.message == WM_QUIT){
done = TRUE;
}else{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}else if(active){
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glViewport(0, 0, window_width, window_height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, (GLdouble)window_width/(GLdouble)window_height, 0.1f, 5000.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRotatef(0, 1,0,0);
glRotatef(0, 0,1,0);
glRotatef(0, 0,0,1);
glTranslatef(0, 0, -zpos);
zpos /= 1.02f;
if(zpos < 0.2f) zpos = 0.2f;
// draw something...
glDisable(GL_DEPTH_TEST);
glDisable(GL_BLEND);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texid);
glColor4f(1,1,1,1);
glBegin(GL_QUADS);
glTexCoord2f(tx1,ty1); glVertex2f(-10,-10);
glTexCoord2f(tx2,ty1); glVertex2f(0,-10);
glTexCoord2f(tx2,ty2); glVertex2f(0,0);
glTexCoord2f(tx1,ty2); glVertex2f(-10,0);
glEnd();
glBegin(GL_QUADS);
glTexCoord2f(tx1,ty1); glVertex2f(0,0);
glTexCoord2f(tx2,ty1); glVertex2f(10,0);
glTexCoord2f(tx2,ty2); glVertex2f(10,10);
glTexCoord2f(tx1,ty2); glVertex2f(0,10);
glEnd();
Sleep(16); // dont run too fast or you break your legs!
SwapBuffers(hDC);
}
}
return 0;
}
И код с несколькими плитками (чтобы увидеть ту же ошибку, когдаменьше увеличения):
/*
Image of the bug: https://i.stack.imgur.com/Drb5U.png
edit: the bug seems to change on different gfx cards, but still visible one way or another!
*/
#pragma comment(lib, "opengl32.lib")
#pragma comment(lib, "Glu32.lib")
#include <windows.h>
#include <stdio.h>
#include <gl/glew.h>
#include <gl/gl.h>
HDC hDC = NULL;
HGLRC hRC = NULL;
HWND hWnd = NULL;
HINSTANCE hInstance;
bool active = 1;
int window_width = 1024;
int window_height = 768;
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam){
switch(uMsg){
case WM_ACTIVATE: {
active = !HIWORD(wParam);
return 0;
}
case WM_CLOSE: {
exit(0);
return 0;
}
case WM_SIZE: {
window_width = LOWORD(lParam);
window_height = HIWORD(lParam);
return 0;
}
}
return DefWindowProc(hWnd,uMsg,wParam,lParam);
}
BOOL create_window(int width, int height){
GLuint PixelFormat;
WNDCLASS wc;
DWORD dwExStyle,dwStyle;
RECT WindowRect;
WindowRect.left = (long)0;
WindowRect.right = (long)width;
WindowRect.top = (long)0;
WindowRect.bottom = (long)height;
hInstance = GetModuleHandle(NULL);
wc.style = CS_HREDRAW|CS_VREDRAW|CS_OWNDC;
wc.lpfnWndProc = (WNDPROC)WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = NULL;
wc.hCursor = NULL;
wc.hbrBackground = NULL;
wc.lpszMenuName = NULL;
wc.lpszClassName = TEXT("test");
if(!RegisterClass(&wc)) return FALSE;
dwExStyle = WS_EX_APPWINDOW|WS_EX_WINDOWEDGE;
dwStyle = WS_OVERLAPPEDWINDOW;
ShowCursor(TRUE);
AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle);
if(!(hWnd = CreateWindowEx(dwExStyle,TEXT("test"),TEXT("test"),dwStyle|WS_CLIPSIBLINGS|WS_CLIPCHILDREN,0,0,width,height,NULL,NULL,hInstance,NULL))) return FALSE;
static PIXELFORMATDESCRIPTOR pfd = {sizeof(PIXELFORMATDESCRIPTOR),1,PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|PFD_DOUBLEBUFFER,PFD_TYPE_RGBA,(BYTE)32,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,PFD_MAIN_PLANE,0,0,0,0};
if(!(hDC = GetDC(hWnd))) return FALSE;
if(!(PixelFormat = ChoosePixelFormat(hDC, &pfd))) return FALSE;
if(!SetPixelFormat(hDC, PixelFormat, &pfd)) return FALSE;
if(!(hRC = wglCreateContext(hDC))) return FALSE;
if(!wglMakeCurrent(hDC, hRC)) return FALSE;
ShowWindow(hWnd, SW_SHOW);
SetForegroundWindow(hWnd);
SetFocus(hWnd);
return TRUE;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow){
if(!create_window(window_width,window_height)){
return 1;
}
glShadeModel(GL_SMOOTH);
glDisable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glClearColor(0,0,0,1);
glColor4f(1,1,1,1);
// create red/yellow checkers pattern with slightly randomized tile pixels:
int img_w = 256;
int img_h = 256;
int tilesize = 16;
unsigned int *data = (unsigned int *)malloc(img_w*img_h*4);
unsigned int colors[] = {0xFF3333, 0xFFFF33};
for(int y = 0; y < img_h; y+=tilesize){
for(int x = 0; x < img_w; x+=tilesize){
unsigned int i = ((x/tilesize)+((y/tilesize)%2))%2;
for(int yy = 0; yy < tilesize; yy++){
for(int xx = 0; xx < tilesize; xx++){
int r = ((colors[i]>>0)&255)-(rand()%30);
int g = ((colors[i]>>8)&255)-(rand()%30);
int b = ((colors[i]>>16)&255)-(rand()%30);
if(r < 0) r = 0;
if(g < 0) g = 0;
if(b < 0) b = 0;
data[(y+yy)*img_w+(x+xx)] = (b << 16) | (g << 8) | r;
}
}
}
}
unsigned int texid = 0;
glGenTextures(1, &texid);
glBindTexture(GL_TEXTURE_2D, texid);
glEnable(GL_TEXTURE_2D);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, img_w, img_h, 0, GL_BGRA, GL_UNSIGNED_BYTE, data);
free(data);
BOOL done = 0;
static MSG msg;
float zpos = 600.0f;
while(!done){
if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)){
if(msg.message == WM_QUIT){
done = TRUE;
}else{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}else if(active){
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glViewport(0, 0, window_width, window_height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, (GLdouble)window_width/(GLdouble)window_height, 0.05f, 5000.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRotatef(0, 1,0,0);
glRotatef(0, 0,1,0);
glRotatef(0, 0,0,1);
glTranslatef(0, 0, -zpos);
zpos /= 1.02f;
if(zpos < 0.1f) zpos = 0.1f;
// draw map from randomly picked tiles:
glDisable(GL_DEPTH_TEST);
glDisable(GL_BLEND);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texid);
glColor4f(1,1,1,1);
static GLuint my_list = 0;
static bool list_made = 0;
if(!list_made){
int map_w = 100;
int map_h = 100;
int tiles_x = img_w/tilesize;
int tiles_y = img_h/tilesize;
my_list = glGenLists(1);
glNewList(my_list, GL_COMPILE);
glBegin(GL_QUADS);
for(int y = -map_h; y < map_h; y++){
for(int x = -map_w; x < map_w; x++){
int xt = (rand()%tiles_x)*tilesize;
int yt = (rand()%tiles_y)*tilesize;
float tx1 = (float)xt/img_w;
float ty1 = (float)yt/img_h;
float tx2 = (float)(xt+tilesize)/img_w;
float ty2 = (float)(yt+tilesize)/img_h;
float x1 = (float)x;
float y1 = (float)y;
float x2 = (float)(x+1);
float y2 = (float)(y+1);
glTexCoord2f(tx1,ty1); glVertex2f(x1,y1);
glTexCoord2f(tx2,ty1); glVertex2f(x2,y1);
glTexCoord2f(tx2,ty2); glVertex2f(x2,y2);
glTexCoord2f(tx1,ty2); glVertex2f(x1,y2);
}
}
glEnd();
glEndList();
list_made = 1;
}
if(list_made){
glCallList(my_list);
}
Sleep(16); // dont run too fast or you break your legs!
SwapBuffers(hDC);
}
}
return 0;
}
Вот также и эта ошибка:
На изображении вышеЯ создал шаблон шашек из красных / желтых плиток.
Я могу исправить это, уменьшив 0,0001f из текстовых кодов tx2 и ty2, но это неприемлемо, так как плитки больше не будут иметь правильные размеры, и это все ещене решает проблему полностью.
Примечание: ошибка появляется только в одном углу (в верхнем правом углу в данном случае).
Я ищу этовизуализировать плитку и быть на 100% уверенным, что из этой текстуры не будет визуализировано ничего, кроме плитки, которую я хочу.
- Разве это не возможно, это нормально в opengl?
- Может ли это быть исправлено шейдером?
Единственный способ узнать, как это исправить - это дополнитькрая плитки того же цвета, что и края плитки.Или создайте 256 отдельных изображений размером 16x16, что недопустимо.
Редактировать: Я тестировал код на другом компьютере: он тоже имеет ту же ошибку, но другую: толькопоказывает проблему в ТОПе четырехугольника и только вверху!и его толщина ТОЛЬКО 1 пиксель за все время (и видна с самого начала, в то время как на моем другом компьютере его нет).в моем другом компьютере ошибка в верхней и правой части, так что я считаю, что это проблема с картой / драйвером gfx ... У меня больше нет компьютеров для тестирования, и я считаю, что ошибка видна так или иначев любом компьютере.если кто-то может проверить код, но вы не видите ошибку, сообщите модель своей карты gfx и, возможно, версию драйвера.