I am learning about 2D graphics some time and I am trying to write a simple program displaying a bitmap like a sprite. I combined several codes to get this one. The application runs runs correctly (I mean it is not crashing), we can see a window, but the image is not showing.
Here is the code:
#include <stdio.h>
#include <windows.h>
#include <GL/gl.h>
#include <GL/glext.h>
#include <GL/glu.h>
LRESULT CALLBACK WindowProcedure(HWND, UINT, WPARAM, LPARAM);
GLuint LoadBMP(const char *fileName);
char szClassName[ ] = "CodeBlocksWindowsApp";
int WINAPI WinMain(HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nCmdShow)
{
HWND hwnd;
MSG Msg;
WNDCLASSEX wincl = {sizeof (WNDCLASSEX), CS_DBLCLKS, WindowProcedure, 0, 0, hThisInstance, LoadIcon (NULL, IDI_APPLICATION), LoadCursor (NULL, IDC_ARROW), (HBRUSH) COLOR_BACKGROUND, NULL, szClassName, LoadIcon (NULL, IDI_APPLICATION)};
if (!RegisterClassEx(&wincl))
return 0;
hwnd = CreateWindowEx(0, szClassName, "Code::Blocks Template Windows App", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 544, 375, HWND_DESKTOP, NULL, hThisInstance, NULL);
ShowWindow (hwnd, nCmdShow);
GLuint texture = LoadBMP("image.bmp");
glEnable(GL_TEXTURE_2D);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,GL_REPLACE);
glBindTexture(GL_TEXTURE_2D, texture);
glBegin(GL_QUADS);
glTexCoord2i(0, 0); glVertex2i(0, 0);
glTexCoord2i(0, 1); glVertex2i(0, 64);
glTexCoord2i(1, 1); glVertex2i(64, 64);
glTexCoord2i(1, 0); glVertex2i(64, 0);
glEnd();
glDisable(GL_TEXTURE_2D);
while (GetMessage (&Msg, NULL, 0, 0))
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return Msg.wParam;
}
LRESULT CALLBACK WindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message) /* handle the Msg */
{
case WM_DESTROY:
PostQuitMessage (0); /* send a WM_QUIT to the message queue */
break;
default: /* for Msg that we don't deal with */
return DefWindowProc (hwnd, message, wParam, lParam);
}
return 0;
}
GLuint LoadBMP(const char *fileName)
{
FILE *file;
unsigned char header[54];
unsigned int dataPos;
unsigned int size;
unsigned int width, height;
unsigned char *data;
file = fopen(fileName, "rb");
if (file == NULL)
{
MessageBox(NULL, "Error: Invaild file path!", "Error", MB_OK);
return false;
}
if (fread(header, 1, 54, file) != 54)
{
MessageBox(NULL, "Error: Invaild file!", "Error", MB_OK);
return false;
}
if (header[0] != 'B' || header[1] != 'M')
{
MessageBox(NULL, "Error: Invaild file!", "Error", MB_OK);
return false;
}
dataPos = *(int*)&(header[0x0A]);
size = *(int*)&(header[0x22]);
width = *(int*)&(header[0x12]);
height = *(int*)&(header[0x16]);
if (size == NULL)
size = width * height * 3;
if (dataPos == NULL)
dataPos = 54;
data = new unsigned char[size];
fread(data, 1, size, file);
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
return texture;
}
Tell me please, what I am doing wrong?
You do create a Window, but you did not create an OpenGL context.
You cannot use GL without a GL context. On windows, the native API to create GL contexts is wgl. This OpeGL.org wiki article explains some of the details of using wgl.
However, you might want to use some GL context and window management library, which abstracts the whole process in a platform-independent way, so that with a few calls, a GL capable window can be cretaed. Have a look at GLFW. This wiki article lists more such libraries.
Related
When I call GLClear without swapping the buffer, it is causing memory leak.
I am not sure if this is a driver issue or if I am doing something wrong.
If anyone can give it a try or have any idea, please tell me.
TL;DR, this is the code summarized. You can find all the code after this block
static bool CloseFlag = false;
LONG WINAPI WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
static PAINTSTRUCT ps;
switch(uMsg)
{
case WM_SIZE:
glViewport(0, 0, LOWORD(lParam), HIWORD(lParam));
PostMessage(hWnd, WM_PAINT, 0, 0);
return 0;
case WM_CHAR:
//Handle input....
return 0;
case WM_CLOSE:
CloseFlag = true;
return 0;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
HWND CreateOpenGLWindow(char* title, int x, int y, int width, int height,
BYTE type, DWORD flags)
{
//Create window (with double buffer) and register it...
}
int main ()
{
hWnd = CreateOpenGLWindow("minimal", 0, 0, 256, 256, PFD_TYPE_RGBA, 0);
hRC = wglCreateContext(hDC);
wglMakeCurrent(hDC, hRC);
gladLoadWGL(hDC)
gladLoadGL()
ShowWindow(hWnd, SW_SHOW);
while(!CloseFlag)
{
//Handles input
while(PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
glClear(GL_COLOR_BUFFER_BIT);
}
wglMakeCurrent(NULL, NULL);
ReleaseDC(hWnd, hDC);
wglDeleteContext(hRC);
DestroyWindow(hWnd);
return 0;
}
Here's a minimum code for reproducing it that uses Win32.
#ifndef UNICODE
#define UNICODE
#define _UNICODE
#endif
#include <windows.h> /* must include this before GL/gl.h */
#include "glad/glad.h"
#include "glad/glad_wgl.h"
#include "wglext.h"
#include <string>
static bool CloseFlag = false;
void display(HDC hDC)
{
/* rotate a triangle around */
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_TRIANGLES);
glColor3f(1.0f, 0.0f, 0.0f);
glVertex2i(0, 1);
glColor3f(0.0f, 1.0f, 0.0f);
glVertex2i(-1, -1);
glColor3f(0.0f, 0.0f, 1.0f);
glVertex2i(1, -1);
glEnd();
glFlush();
SwapBuffers(hDC);
}
void JustClear()
{
glClear(GL_COLOR_BUFFER_BIT);
}
LONG WINAPI WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
static PAINTSTRUCT ps;
switch(uMsg)
{
case WM_SIZE:
glViewport(0, 0, LOWORD(lParam), HIWORD(lParam));
PostMessage(hWnd, WM_PAINT, 0, 0);
return 0;
case WM_CHAR:
switch (wParam)
{
case 27: /* ESC key */
//PostQuitMessage(0);
CloseFlag = true;
break;
}
return 0;
case WM_CLOSE:
CloseFlag = true;
//PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
HWND CreateOpenGLWindow(char* title, int x, int y, int width, int height,
BYTE type, DWORD flags)
{
int pf;
HDC hDC;
HWND hWnd;
WNDCLASS wc;
PIXELFORMATDESCRIPTOR pfd;
static HINSTANCE hInstance = 0;
/* only register the window class once - use hInstance as a flag. */
if (!hInstance) {
hInstance = GetModuleHandle(NULL);
wc.style = CS_OWNDC;
wc.lpfnWndProc = (WNDPROC)WindowProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = NULL;
wc.lpszMenuName = NULL;
wc.lpszClassName = L"OpenGL";
if (!RegisterClass(&wc)) {
return NULL;
}
}
std::wstring className = L"OpenGL";
hWnd = CreateWindow(className.c_str(), className.c_str(), WS_OVERLAPPEDWINDOW |
WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
x, y, width, height, NULL, NULL, hInstance, NULL);
if (hWnd == NULL) {
return NULL;
}
hDC = GetDC(hWnd);
/* there is no guarantee that the contents of the stack that become
the pfd are zeroed, therefore _make sure_ to clear these bits. */
memset(&pfd, 0, sizeof(pfd));
pfd.nSize = sizeof(pfd);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | flags;
pfd.iPixelType = type;
pfd.cColorBits = 32;
pf = ChoosePixelFormat(hDC, &pfd);
if (pf == 0) {
return 0;
}
if (SetPixelFormat(hDC, pf, &pfd) == FALSE) {
return 0;
}
DescribePixelFormat(hDC, pf, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
ReleaseDC(hWnd, hDC);
return hWnd;
}
int main ()
{
HDC hDC; /* device context */
HGLRC hRC; /* opengl context */
HWND hWnd; /* window */
MSG msg; /* message */
hWnd = CreateOpenGLWindow("minimal", 0, 0, 256, 256, PFD_TYPE_RGBA, 0);
if (hWnd == NULL)
exit(1);
hDC = GetDC(hWnd);
hRC = wglCreateContext(hDC);
wglMakeCurrent(hDC, hRC);
if(!gladLoadWGL(hDC))
{
return -1;
}
if (!gladLoadGL()) //Load Glad
{
return -1;
}
ShowWindow(hWnd, SW_SHOW);
while(!CloseFlag)
{
//Handles input
while(PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
//Render
//display(hDC);
JustClear();
}
wglMakeCurrent(NULL, NULL);
ReleaseDC(hWnd, hDC);
wglDeleteContext(hRC);
DestroyWindow(hWnd);
return 0;
}
wglext.h is from here
Here's the OpenGL glad config
/*
OpenGL loader generated by glad 0.1.36 on Fri Oct 28 11:12:34 2022.
Language/Generator: C/C++
Specification: gl
APIs: gl=3.3
Profile: compatibility
Extensions:
Loader: True
Local files: False
Omit khrplatform: False
Reproducible: False
Commandline:
--profile="compatibility" --api="gl=3.3" --generator="c" --spec="gl" --extensions=""
Online:
https://glad.dav1d.de/#profile=compatibility&language=c&specification=gl&loader=on&api=gl%3D3.3
*/
and Glad wgl 1.0 with all the extensions
and here's the CMake I used
cmake_minimum_required(VERSION 3.14)
set (CMAKE_CXX_STANDARD 11)
# For Clang to do parsing
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# set the project name
project(Example)
add_executable(EXAMPLE_EXE ${CMAKE_CURRENT_LIST_DIR}/Src/main.cpp)
add_subdirectory("${CMAKE_CURRENT_LIST_DIR}/External/glad_v0.1.36")
find_package(OpenGL REQUIRED)
target_include_directories(EXAMPLE_EXE PUBLIC "${CMAKE_CURRENT_LIST_DIR}/External/wglExt")
target_link_libraries(EXAMPLE_EXE PUBLIC OpenGL::GL glad)
I'm trying to make a fullscreen transparent window on the desktop that i can render on with opengl.
I don't want to overflow the screen but so far that seems to be the only way i can. It's a pretty dirty hack imo and would hope someone knows of a professional solution.
Here's the code:
// libs needed to compile: opengl32 gdi32 dwmapi
#include <windows.h>
#include <GL/gl.h>
#include <dwmapi.h>
HDC hDC;
HGLRC hRC;
HWND hWnd;
bool running=true;
int w=GetSystemMetrics(SM_CXSCREEN),h=GetSystemMetrics(SM_CYSCREEN);
void CreateContext(){
PIXELFORMATDESCRIPTOR pfd; hDC=GetDC(hWnd);
SetPixelFormat(hDC,ChoosePixelFormat(hDC,&pfd),&pfd);
hRC=wglCreateContext(hDC); wglMakeCurrent(hDC,hRC);
}
void EnableTransparency(){DWM_BLURBEHIND b={DWM_BB_ENABLE|DWM_BB_BLURREGION,TRUE,CreateRectRgn(0,0,-1,-1)}; DwmEnableBlurBehindWindow(hWnd,&b);}
LRESULT CALLBACK WndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam){
switch(uMsg){
case WM_CLOSE: running=false; return 0;
case WM_KEYDOWN: if(wParam==VK_ESCAPE){running=false;} return 0;
}return DefWindowProc(hWnd,uMsg,wParam,lParam);
}
void CreateWin(){
WNDCLASS wc={};
wc.lpfnWndProc=WndProc;
wc.hInstance=GetModuleHandle(NULL);
wc.hCursor=LoadCursor(NULL,IDC_ARROW);
wc.lpszClassName="OpenGL";
RegisterClass(&wc);
hWnd = CreateWindow(wc.lpszClassName,"Title",WS_POPUP,0,-1,w,h+1,0,0,wc.hInstance,0); // increasing height by 1 pixel
ShowWindow(hWnd,SW_SHOW);
EnableTransparency();
CreateContext();
}
void PumpMessages(){MSG msg; while(PeekMessage(&msg,NULL,0,0,PM_REMOVE))DispatchMessage(&msg);}
int main(){
CreateWin();
glViewport(0,0,w,h); // the visible screen area (excluding h+1 overflow)
while(running){
PumpMessages();
glClearColor(0,0,0,1); glClear(GL_COLOR_BUFFER_BIT); // fill solid black
glBegin(GL_TRIANGLES); // transparent triangular window
glColor4f(1,0,0,0.5f); glVertex3f( 0, 1,0); // red (center)
glColor4f(0,1,0,0.5f); glVertex3f(-1,-1,0); // green (left)
glColor4f(0,0,1,0.5f); glVertex3f( 1,-1,0); // blue (right)
glEnd();
SwapBuffers(hDC);
}
return 0;
}
When running your code, I don't actually get any transparency, so I can't understand why you are needing to overflow the screen. But here's how I changed your code to work for me, and without overflowing the screen.
// libs needed to compile: opengl32 gdi32 dwmapi
#include <windows.h>
#include <GL/gl.h>
#include <dwmapi.h>
HDC hDC;
HGLRC hRC;
HWND hWnd;
bool running = true;
int w = GetSystemMetrics(SM_CXSCREEN), h = GetSystemMetrics(SM_CYSCREEN);
void CreateContext() {
PIXELFORMATDESCRIPTOR pfd; hDC = GetDC(hWnd);
SetPixelFormat(hDC, ChoosePixelFormat(hDC, &pfd), &pfd);
hRC = wglCreateContext(hDC); wglMakeCurrent(hDC, hRC);
}
void EnableTransparency() {
SetLayeredWindowAttributes(hWnd, NULL, NULL, NULL);
const MARGINS margins = { -1 };
DwmExtendFrameIntoClientArea(hWnd, &margins);
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
case WM_CLOSE: running = false; return 0;
case WM_KEYDOWN: if (wParam == VK_ESCAPE) { running = false; } return 0;
}return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
void CreateWin() {
WNDCLASS wc = {};
wc.lpfnWndProc = WndProc;
wc.hInstance = GetModuleHandle(NULL);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.lpszClassName = "OpenGL";
RegisterClass(&wc);
hWnd = CreateWindowEx(WS_EX_LAYERED, wc.lpszClassName, "Title", WS_POPUP, 0, 0, w, h, 0, 0, wc.hInstance, 0);
ShowWindow(hWnd, SW_SHOW);
CreateContext();
EnableTransparency();
}
void PumpMessages() { MSG msg; while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))DispatchMessage(&msg); }
int main() {
CreateWin();
glViewport(0, 0, w, h); // the visible screen area
while (running) {
PumpMessages();
glClearColor(0, 0, 0, 1); glClear(GL_COLOR_BUFFER_BIT); // fill solid black
glBegin(GL_TRIANGLES); // transparent triangular window
glColor4f(1, 0, 0, 0.5f); glVertex3f(0, 1, 0); // red (center)
glColor4f(0, 1, 0, 0.5f); glVertex3f(-1, -1, 0); // green (left)
glColor4f(0, 0, 1, 0.5f); glVertex3f(1, -1, 0); // blue (right)
glEnd();
SwapBuffers(hDC);
}
return 0;
}
Checking error codes has been left out. Essentially, we use a window with the layered style to get transparency. We call SetLayeredWindowAttributes with no flags, because we are not using any of these layered window features, but we need to call the function for the window to become visible.
Ok so I'm trying to figure out how this game works. It isn't created by me but I was intrigued at how it combines two textures, cuts out a circle and renders that portion to the screen depending on the character position.
Texture #1 is Map.bmp:
Texture #2 is the MM.bmp:
It then combines them to create a circular cut out within the Giant Map.
I've written an Emulator to do exactly the same commands as the game and it does cut it out the same way the game does.
The code is as follows:
Bitmap.h:
#ifndef BITMAP_H_INCLUDED
#define BITMAP_H_INCLUDED
#include <iostream>
#include <fstream>
#include <vector>
#include <stdexcept>
class Bitmap
{
private:
std::vector<std::uint8_t> Pixels;
std::uint32_t width, height;
std::uint16_t BitsPerPixel;
public:
Bitmap(const char* FilePath);
inline std::uint16_t Bits()
{
return BitsPerPixel;
}
inline int Width() const
{
return width;
}
inline int Height() const
{
return height;
}
inline std::uint8_t* GetPixels()
{
return Pixels.data();
}
};
#endif // BITMAP_H_INCLUDED
Bitmap.cpp:
#include "Bitmap.h"
Bitmap::Bitmap(const char* FilePath) : Pixels(0), width(0), height(0), BitsPerPixel(0)
{
std::fstream hFile(FilePath, std::ios::in | std::ios::binary);
if (!hFile.is_open()) throw std::invalid_argument("Error: File Not Found.");
hFile.seekg(0, std::ios::end);
int Length = hFile.tellg();
hFile.seekg(0, std::ios::beg);
std::vector<std::uint8_t> FileInfo(Length);
hFile.read(reinterpret_cast<char*>(FileInfo.data()), 54);
if(FileInfo[0] != 'B' && FileInfo[1] != 'M')
{
hFile.close();
throw std::invalid_argument("Error: Invalid File Format. Bitmap Required.");
}
if (FileInfo[28] != 24 && FileInfo[28] != 32)
{
hFile.close();
throw std::invalid_argument("Error: Invalid File Format. 24 or 32 bit Image Required.");
}
BitsPerPixel = FileInfo[28];
width = FileInfo[18] + (FileInfo[19] << 8);
height = FileInfo[22] + (FileInfo[23] << 8);
std::uint32_t PixelsOffset = FileInfo[10] + (FileInfo[11] << 8);
std::uint32_t size = ((width * BitsPerPixel + 31) / 32) * 4 * height;
Pixels.resize(size);
hFile.seekg (PixelsOffset, std::ios::beg);
hFile.read(reinterpret_cast<char*>(Pixels.data()), size);
hFile.close();
}
and finally Main.cpp which emulates the game:
Main.cpp:
#include <windows.h>
#include <iostream>
#include <GL/gl.h>
#include <GL/glext.h>
#include "Bitmap.h"
int Width = 781, Height = 591;
std::string Title = "Example";
std::string ClassName = "Example";
template<typename T, typename U>
bool xCast(T &FunctionDefinition, U FunctionAddress)
{
return (FunctionDefinition = reinterpret_cast<T>(FunctionAddress));
}
void EnableOpenGL(HWND hwnd, HDC* hDC, HGLRC* hRC);
void DisableOpenGL (HWND hwnd, HDC hDC, HGLRC hRC);
GLuint LoadTexture(std::string FilePath, GLenum Target);
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nCmdShow)
{
WNDCLASSEX WndClass =
{
sizeof(WNDCLASSEX), CS_DBLCLKS, WindowProcedure,
0, 0, GetModuleHandle(nullptr), LoadIcon(nullptr, IDI_APPLICATION),
LoadCursor(nullptr, IDC_ARROW), HBRUSH(COLOR_WINDOW + 1),
nullptr, ClassName.c_str(), LoadIcon (nullptr, IDI_APPLICATION)
};
if(RegisterClassEx(&WndClass))
{
HDC DC = nullptr;
HGLRC HRC = nullptr;
HWND WindowHandle = CreateWindowEx(0, ClassName.c_str(), Title.c_str(), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, Width, Height, nullptr, nullptr, GetModuleHandle(nullptr), nullptr);
if(WindowHandle)
{
bool Quit = false;
MSG msg = {nullptr};
EnableOpenGL(WindowHandle, &DC, &HRC);
ShowWindow(WindowHandle, SW_SHOWDEFAULT);
glViewport(0, 0, 765, 553);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0, 765, 553, 0.0, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
void (__stdcall *ptr_glActiveTextureARB) (GLenum texture);
void (__stdcall *ptr_glMultiTexCoord2fARB) (GLenum target, GLfloat s, GLfloat t);
xCast(ptr_glActiveTextureARB, wglGetProcAddress("glActiveTextureARB"));
xCast(ptr_glMultiTexCoord2fARB, wglGetProcAddress("glMultiTexCoord2fARB"));
GLint Map = LoadTexture("Map.bmp", GL_TEXTURE_2D);
GLint MM = LoadTexture("MM.bmp", GL_TEXTURE_RECTANGLE);
while(!Quit)
{
if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT)
{
Quit = true;
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
else
{
glPushMatrix();
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//Combines the two textures and draws them to the screen.
glEnable(GL_SCISSOR_TEST);
glScissor(550, 341, 154, 154);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDisable(GL_TEXTURE_RECTANGLE);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, Map);
ptr_glActiveTextureARB(GL_TEXTURE1);
glEnable(GL_TEXTURE_RECTANGLE);
glBindTexture(GL_TEXTURE_RECTANGLE, MM);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
glBegin(GL_QUADS);
glColor3f(1, 1, 1);
ptr_glMultiTexCoord2fARB(GL_TEXTURE0, 0, 1);
ptr_glMultiTexCoord2fARB(GL_TEXTURE1, -194.55215, 353.57529);
glVertex2f(355.44785, -141.57529);
ptr_glMultiTexCoord2fARB(GL_TEXTURE0, 0, 0);
ptr_glMultiTexCoord2fARB(GL_TEXTURE1, -212.4122, -194.13358);
glVertex2f(337.5878, 406.13358);
ptr_glMultiTexCoord2fARB(GL_TEXTURE0, 1, 0);
ptr_glMultiTexCoord2fARB(GL_TEXTURE1, 335.29663, -211.99362);
glVertex2f(885.29663, 423.99362);
ptr_glMultiTexCoord2fARB(GL_TEXTURE0, 1, 1);
ptr_glMultiTexCoord2fARB(GL_TEXTURE1, 353.15674, 335.71524);
glVertex2f(903.15674, -123.71524);
glEnd();
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);
glDisable(GL_TEXTURE_RECTANGLE);
ptr_glActiveTextureARB(GL_TEXTURE0);
glDisable(GL_TEXTURE_2D);
glDisable(GL_SCISSOR_TEST);
glPopMatrix();
SwapBuffers(DC);
Sleep(1);
}
}
DisableOpenGL(WindowHandle, DC, HRC);
return msg.wParam;
}
}
return 0;
}
//Loads textures:
GLuint LoadTexture(std::string FilePath, GLenum Target)
{
Bitmap Img(FilePath.c_str());
GLuint ID = 0;
glGenTextures(1, &ID);
glBindTexture(Target, ID);
glTexParameteri(Target, GL_TEXTURE_WRAP_S, Target == GL_TEXTURE_2D ? GL_REPEAT : GL_CLAMP_TO_EDGE);
glTexParameteri(Target, GL_TEXTURE_WRAP_T, Target == GL_TEXTURE_2D ? GL_REPEAT : GL_CLAMP_TO_EDGE);
glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(Target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(Target, 0, Img.Bits() == 32 ? GL_RGBA : GL_RGB, Img.Width(), Img.Height(), 0, Img.Bits() == 32 ? GL_BGRA : GL_BGR, GL_UNSIGNED_BYTE, Img.GetPixels());
return ID;
}
void EnableOpenGL(HWND hwnd, HDC* hDC, HGLRC* hRC)
{
PIXELFORMATDESCRIPTOR pfd;
int iFormat;
*hDC = GetDC(hwnd);
ZeroMemory(&pfd, sizeof(pfd));
pfd.nSize = sizeof(pfd);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 24;
pfd.cDepthBits = 16;
pfd.iLayerType = PFD_MAIN_PLANE;
iFormat = ChoosePixelFormat(*hDC, &pfd);
SetPixelFormat(*hDC, iFormat, &pfd);
*hRC = wglCreateContext(*hDC);
wglMakeCurrent(*hDC, *hRC);
}
void DisableOpenGL (HWND hwnd, HDC hDC, HGLRC hRC)
{
wglMakeCurrent(NULL, NULL);
wglDeleteContext(hRC);
ReleaseDC(hwnd, hDC);
}
LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_KEYDOWN:
{
switch(wParam)
{
case VK_ESCAPE:
PostQuitMessage(0);
break;
}
}
break;
case WM_DESTROY:
PostQuitMessage (0);
break;
default:
return DefWindowProc (hwnd, message, wParam, lParam);
}
return 0;
}
And the output looks like:
What I want to know is, how does these negative coordinates work. For example, the glMultiTexCoord2fArb and the glVertex2f have coordinates that are out of bounds of the viewport. The viewport is 765x553. It also doesn't fit into the scissor area.
How does it figure out what portions of the texture to merge and is there a way I can do that myself so that I don't have to use the negative coords? In other words, how can I translate those negative coordinates into regular positive ones and figure out which portions of both textures are merged? I've written the example above to test and figure out how it works but I just can't seem to see how these negative coords and wrapping fit in.
This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
I have an opengl c++ code for reading .ply file. I want to read keyboard arrow keys(up,down,right,left) for move a point on the screen. I used glutKeyboardFunc function but i have an error:
Unhandled exception at 0x1000bb1e in opengl3.exe: 0xC0000005: Access violation reading location 0x00000070.
On this line:
glutKeyboardFunc(keyPressed);
#include <windows.h>
#include <gl/gl.h>
#include <gl/glu.h>
#include <gl/glut.h>
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <cmath>
#include <string>
#include <conio.h>
HWND hWnd;
HDC hDC;
HGLRC hRC;
// Set up pixel format for graphics initialization
void SetupPixelFormat()
{
PIXELFORMATDESCRIPTOR pfd, *ppfd;
int pixelformat;
ppfd = &pfd;
ppfd->nSize = sizeof(PIXELFORMATDESCRIPTOR);
ppfd->nVersion = 1;
ppfd->dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
ppfd->dwLayerMask = PFD_MAIN_PLANE;
ppfd->iPixelType = PFD_TYPE_COLORINDEX;
ppfd->cColorBits = 16;
ppfd->cDepthBits = 16;
ppfd->cAccumBits = 0;
ppfd->cStencilBits = 0;
pixelformat = ChoosePixelFormat(hDC, ppfd);
SetPixelFormat(hDC, pixelformat, ppfd);
}
void InitGraphics()
{
hDC = GetDC(hWnd);
SetupPixelFormat();
hRC = wglCreateContext(hDC);
wglMakeCurrent(hDC, hRC);
glClearColor(0, 0, 0, 0.5);
glClearDepth(1.0);
glEnable(GL_DEPTH_TEST);
}
// Resize graphics to fit window
void ResizeGraphics()
{
// Get new window size
RECT rect;
int width, height;
GLfloat aspect;
GetClientRect(hWnd, &rect);
width = rect.right;
height = rect.bottom;
aspect = (GLfloat)width / height;
// Adjust graphics to window size
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0, aspect, 1.0, 100.0);
glMatrixMode(GL_MODELVIEW);
}
// Draw frame
void DrawGraphics()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Set location in front of camera
glLoadIdentity();
glTranslated(0, 0, -10);
// Draw a square
glBegin(GL_QUADS);
glColor3d(100, 200, 30);
/*
glVertex3d(-2, 2, 0);
glVertex3d(2, 2, 0);
glVertex3d(2, -2, 0);
glVertex3d(-2, -2, 0);
*/
//FILE * file = fopen("D:\\dart.ply","r");
FILE * file = fopen("mosalas.ply","r");
if (file!=NULL)
{
fseek(file,0,SEEK_END);
long fileSize = ftell(file);
float* Vertex_Buffer;
try
{
Vertex_Buffer = (float*) malloc (ftell(file));
}
catch (char* )
{
//return -1;
}
//if (Vertex_Buffer == NULL) return -1;
fseek(file,0,SEEK_SET);
//Faces_Triangles = (float*) malloc(fileSize*sizeof(float));
//Normals = (float*) malloc(fileSize*sizeof(float));
if (file)
{
int i = 0;
int temp = 0;
int quads_index = 0;
int triangle_index = 0;
int normal_index = 0;
char buffer[1000];
fgets(buffer,300,file); // ply
// READ HEADER
// -----------------
int TotalConnectedPoints;
// Find number of vertexes
while ( strncmp( "element vertex", buffer,strlen("element vertex")) != 0 )
{
fgets(buffer,300,file); // format
}
strcpy(buffer, buffer+strlen("element vertex"));
sscanf(buffer,"%i", &TotalConnectedPoints);
int TotalFaces;
// Find number of face
fseek(file,0,SEEK_SET);
while ( strncmp( "element face", buffer,strlen("element face")) != 0 )
{
fgets(buffer,300,file); // format
}
strcpy(buffer, buffer+strlen("element face"));
sscanf(buffer,"%i", &TotalFaces);
// go to end_header
while ( strncmp( "end_header", buffer,strlen("end_header")) != 0 )
{
fgets(buffer,300,file); // format
}
i =0;
float* ver0,ver1,ver2,ver3;
//char* key[100];
for (int iterator = 0; iterator < TotalConnectedPoints; iterator++)
{
fgets(buffer,300,file);
//sscanf(buffer,"%f %f %f", &Vertex_Buffer[i], &Vertex_Buffer[i+1], &Vertex_Buffer[i+2]);
sscanf(buffer,"%f %f %f", &ver1, &ver2, &ver3);
glNormal3f(ver1, ver2, ver3);
glVertex3d(ver1, ver2, ver3);
//glVertex3f(ver1, ver2, ver3);
i += 3;
}
}
}
glPushMatrix();
glBegin;
glTranslatef(-10,5,0);
glColor3f(1,1,1);
glRotatef(90,0,1,0);
glutSolidCone(0.25, 15, 20, 20);
glEnd();
glPopMatrix();
//glutMouseFunc(0,0,0);
/*
glVertex3d(1.000000, 1.000000, 6);
glVertex3d(3.000000, 0.000000, 4);
glVertex3d(0.000000, 0.000000, 4);
glVertex3d(0.000000, 3.000000, 4);
glVertex3d(1.500000, 0.500000, 0);*/
glEnd();
// Show the new scene
SwapBuffers(hDC);/**/
}
void keyPressed (unsigned char key, int x, int y) {
}
// Handle window events and messages
LONG WINAPI MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_SIZE:
ResizeGraphics();
break;
case WM_CLOSE:
DestroyWindow(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
// Default event handler
default:
return DefWindowProc (hWnd, uMsg, wParam, lParam);
break;
}
return 1;
}
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
const LPCWSTR appname = TEXT("OpenGL Sample");
WNDCLASS wndclass;
MSG msg;
// Define the window class
wndclass.style = 0;
wndclass.lpfnWndProc = (WNDPROC)MainWndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon(hInstance, appname);
wndclass.hCursor = LoadCursor(NULL,IDC_ARROW);
wndclass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wndclass.lpszMenuName = appname;
wndclass.lpszClassName = appname;
// Register the window class
if (!RegisterClass(&wndclass)) return FALSE;
// Create the window
hWnd = CreateWindow(
appname,
appname,
WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
CW_USEDEFAULT,
CW_USEDEFAULT,
800,
600,
NULL,
NULL,
hInstance,
NULL);
if (!hWnd) return FALSE;
// Initialize OpenGL
InitGraphics();
// Display the window
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
DrawGraphics();
// Event loop
int key;
int asgh = 0;
POINT pt;
/**/while (1)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) == TRUE)
{
if (!GetMessage(&msg, NULL, 0, 0))
return TRUE;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
glutKeyboardFunc(keyPressed);
DrawGraphics();
}
wglDeleteContext(hRC);
ReleaseDC(hWnd, hDC);
}
The program you posted lacks a call to glutInit().
Furthermore you're doing all of the platform-specific window management and context creation that GLUT is supposed abstract away.
Bottom line: If you want to use GLUT, use GLUT. If you want to use Win32, use Win32. Don't try to mix-and-match.
My problem is that my program isn't displaying anything on screen.
This is the "main.cpp" code:
#include "paStdAfx.h"
#include "OpenGL.h"
HDC hDC = NULL;
HGLRC hRC = NULL;
HWND hwnd = NULL;
HINSTANCE hInstance = GetModuleHandle(NULL);
const wchar_t* szClassName = _T("*project name :3*");
static std::wstring Titles[] = {
_T("*project name :3* - 100% free!"),
_T("*project name :3* - 100% OpenGL!"),
_T("*project name :3* - Not cross platform!"),
_T("*project name :3* - Rawr"),
_T("*project name :3* - Entirely C++!"),
_T("*project name :3* - Woo, /r/gamedev!"),
_T("*project name :3* - Platypi, platypi everywhere."),
_T("*project name :3* - Nom nom nom"),
_T("*project name :3* - Thanks, StackExchange!"),
_T("*project name :3* - DRM Free!"),
_T("*project name :3* - <3"),
_T("*project name :3* - Minecraft is also fun!")
};
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
BOOL CreateOpenGLWindow(const wchar_t*, int, int, int);
OpenGL ogl;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int iCmdShow)
{
srand(time(NULL));
const std::wstring wtt = Titles[rand() % 11];
const wchar_t* WindowTitle = wtt.c_str();
BOOL done = FALSE;
MSG msg;
if(!CreateOpenGLWindow(WindowTitle, 800, 600, 32)){ MessageBox(NULL, _T("Could not create window :("), _T("Error!"), MB_OK | MB_ICONERROR); exit(EXIT_FAILURE); }
while(!done)
{
if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if(msg.message == WM_QUIT)
done = TRUE;
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
else
{
ogl.RenderGLScene();
SwapBuffers(hDC);
}
}
ogl.KillOpenGL(hwnd, hDC, hRC);
return 0;
}
BOOL CreateOpenGLWindow(const wchar_t* title, int width, int height, int bits)
{
WNDCLASSEX wcx = {0};
DWORD dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
DWORD dwStyle = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX;
wcx.cbSize = sizeof(WNDCLASSEX);
wcx.style = CS_OWNDC;
wcx.lpfnWndProc = WndProc;
wcx.cbClsExtra = 0;
wcx.cbWndExtra = 0;
wcx.hInstance = hInstance;
wcx.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_PROGRAMICON));
wcx.hCursor = LoadCursor(NULL, IDC_ARROW);
wcx.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
wcx.lpszClassName = szClassName;
wcx.lpszMenuName = NULL;
wcx.hIconSm = (HICON) LoadImage(hInstance, MAKEINTRESOURCE(IDI_PROGRAMICON), IMAGE_ICON, 16, 16, 0);
if(!RegisterClassEx(&wcx)){ MessageBox(NULL, _T("Failed to register window!"), _T("Error! :("), MB_OK | MB_ICONERROR); exit(EXIT_FAILURE); }
if(!(hwnd = CreateWindowEx(dwExStyle, szClassName, title, dwStyle, 200, 69, width, height, NULL, NULL, hInstance, NULL))){ MessageBox(NULL, _T("Failed to create the window!"), _T("Error! :("), MB_OK | MB_ICONERROR); exit(EXIT_FAILURE); }
ogl.CreateOpenGLContext(hwnd, &hDC, &hRC);
ogl.PrepareOpenGLScene();
ogl.ResizeGLScene(width, height);
ShowWindow(hwnd, SW_SHOW);
SetForegroundWindow(hwnd);
SetFocus(hwnd);
return TRUE;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_CREATE:
ogl.ProgramIcon(hwnd);
break;
case WM_KEYDOWN:
switch(wParam)
{
case VK_ESCAPE:
PostQuitMessage(0);
break;
}
break;
case WM_CLOSE:
PostQuitMessage(0);
break;
case WM_DESTROY:
return 0;
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
and this is the "OpenGL.cpp" code:
#include "paStdAfx.h"
#include "OpenGL.h"
GLvoid OpenGL::CreateOpenGLContext(HWND hwnd, HDC* hDC, HGLRC* hRC)
{
PIXELFORMATDESCRIPTOR pfd;
HGLRC tempContext;
memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DOUBLEBUFFER | PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 32;
pfd.cDepthBits = 32;
pfd.iLayerType = PFD_MAIN_PLANE;
*hDC = GetDC(hwnd);
int PixelFormat = ChoosePixelFormat(*hDC, &pfd);
if(PixelFormat == 0){ MessageBox(NULL, _T("Could not choose pixel format :("), _T("Error!"), MB_OK | MB_ICONERROR); exit(EXIT_FAILURE); }
if(!SetPixelFormat(*hDC, PixelFormat, &pfd)){ MessageBox(NULL, _T("Could not set pixel format :("), _T("Error!"), MB_OK | MB_ICONERROR); exit(3); }
tempContext = wglCreateContext(*hDC);
wglMakeCurrent(*hDC, tempContext);
GLenum err = glewInit();
if(GLEW_OK != err){ MessageBox(NULL, _T("Failed to initialize GLEW! :("), _T("Warning!"), MB_OK | MB_ICONINFORMATION); }
int attribs[] = {
WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
WGL_CONTEXT_MINOR_VERSION_ARB, 1,
WGL_CONTEXT_FLAGS_ARB,
WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
0
};
if(!glewIsSupported("GL_VERSION_3_1")){ MessageBox(NULL, _T("OpenGL 3.1 not supported :("), _T("Warning!"), MB_OK | MB_ICONERROR); }
if(wglewIsSupported("WGL_ARB_create_context") == 1)
{
*hRC = wglCreateContextAttribsARB(*hDC, 0, attribs);
wglMakeCurrent(NULL, NULL);
wglDeleteContext(tempContext);
wglMakeCurrent(*hDC, *hRC);
}
else{ *hRC = tempContext; }
const char* GLVersionString = (char*) glGetString(GL_VERSION);
int OpenGLVersion[2];
glGetIntegerv(GL_MAJOR_VERSION, &OpenGLVersion[0]);
glGetIntegerv(GL_MINOR_VERSION, &OpenGLVersion[1]);
}
GLvoid OpenGL::PrepareOpenGLScene(GLvoid)
{
glClearColor(0.0f, 0.6f, 1.0f, 0.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
}
GLvoid OpenGL::RenderGLScene(GLvoid)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
/* Begin OpenGL Rendering */
/* End OpenGL Rendering */
}
GLvoid OpenGL::ResizeGLScene(int w, int h)
{
float ratio = 1.0 * w / h;
if(h == 0)
h = 1;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, ratio, 0.1f, 1000.0f);
glViewport(0, 0, w, h);
}
GLvoid OpenGL::ProgramIcon(HWND hwnd)
{
HICON hIcon, hIconSm;
hIcon = (HICON) LoadImage(NULL, _T("data/icon.ico"), IMAGE_ICON, 32, 32, LR_LOADFROMFILE);
if(hIcon)
SendMessage(hwnd, WM_SETICON, ICON_BIG, (LPARAM)hIcon);
else
MessageBox(NULL, _T("Could not load the big icon! :("), _T("Error!"), MB_OK | MB_ICONERROR);
//---------------------------------------------------------------------------------------------//
hIconSm = (HICON) LoadImage(NULL, _T("data/icon.ico"), IMAGE_ICON, 16, 16, LR_LOADFROMFILE);
if(hIconSm)
SendMessage(hwnd, WM_SETICON, ICON_SMALL, (LPARAM)hIconSm);
else
MessageBox(NULL, _T("Could not load the small icon! :("), _T("Error!"), MB_OK | MB_ICONERROR);
}
GLvoid OpenGL::KillOpenGL(HWND hwnd, HDC hDC, HGLRC hRC)
{
wglMakeCurrent(NULL, NULL);
wglDeleteContext(hRC);
ReleaseDC(hwnd, hDC);
}
All the rendering code would go inside the "RenderGLScene" function inside of OpenGL.cpp, but when I place code to render basic things like trianlges or squares on the screen nothing appears. I have tried tinkering with the "gluLookAt()" function and the "gluPerspective()" function as well because I think those might be the source of my problem. I have tried both VBO and the older method that uses glBegin()/glEnd().
You create a double buffered context, but I don't see you performing a buffer swap (wglSwapBuffers) after finishing the rendering. Without a buffer swap you won't see anything.
What does your render code look like. Remember that the camera always is placed in the origin, which means that you need to draw things at negative z coordinates.
If you created a core context all drawing must be done using a VAO. Check the glError() return codes to see what the glDraw*() reports back.