GIMP-Exported png remembers deleted layers - c

I've made a set of similar images in GIMP. For each new image, I traced over the previous image and drew a different letter in the center, getting rid of the letter of the previous image. This is what my image looks like:
I have a C program which uses libpng to load the image, then displays it as a texture in OpenGL. This is what I get:
The letter from the previous image is behind the one for this image. It doesn't show up in GIMP anymore (or Atom), and I only have one layer. Why might this be happening?
Code that might be suspect:
int load_texture(const char* filename, GLuint* ptexture) {
FILE* fp = fopen(filename, "rb");
if (!fp) {
return LOAD_TEXTURE__FILE_NOT_FOUND;
}
unsigned char bytes[8];
fread(bytes, 1, 8, fp);
bool is_png = !png_sig_cmp(bytes, 0, 8);
if (!is_png) {
return LOAD_TEXTURE__FILE_NOT_PNG;
}
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!png_ptr) {
return LOAD_TEXTURE__PNG_READ_STRUCT_FAILURE;
}
png_infop info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr) {
png_destroy_read_struct(&png_ptr, (png_infopp)(NULL), (png_infopp)(NULL));
return LOAD_TEXTURE__PNG_INFO_PTR_FAILURE;
}
png_infop end_info = png_create_info_struct(png_ptr);
if (!end_info) {
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)(NULL));
return LOAD_TEXTURE__PNG_END_INFO_FAILURE;
}
if (setjmp(png_jmpbuf(png_ptr))) {
return LOAD_TEXTURE__PNG_JMPBUF_FAILURE;
}
png_init_io(png_ptr, fp);
png_set_sig_bytes(png_ptr, 8);
png_read_info(png_ptr, info_ptr);
int width = png_get_image_width(png_ptr, info_ptr);
int height = png_get_image_height(png_ptr, info_ptr);
png_byte color_type = png_get_color_type(png_ptr, info_ptr);
png_byte bit_depth = png_get_bit_depth(png_ptr, info_ptr);
int number_of_passes = png_set_interlace_handling(png_ptr);
png_read_update_info(png_ptr, info_ptr);
if (setjmp(png_jmpbuf(png_ptr))) {
return LOAD_TEXTURE__PNG_JMPBUF_FAILURE;
}
png_bytep* row_pointers = (png_bytep*)(malloc(sizeof(png_bytep) * height));
for (int y = 0; y < height; y++) {
row_pointers[y] = (png_byte*)(malloc(png_get_rowbytes(png_ptr,info_ptr)));
}
png_read_image(png_ptr, row_pointers);
unsigned char* data = malloc(height * png_get_rowbytes(png_ptr, info_ptr));
fclose(fp);
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
memcpy(data + (i * width * 4 + j * 4), &row_pointers[i][j * 4], 4);
}
}
for (int y = 0; y < height; y++) {
free(row_pointers[y]);
}
free(row_pointers);
GLuint texture_id = 0;
glGenTextures(1, &texture_id);
glBindTexture(GL_TEXTURE_2D, texture_id);
GLuint gl_color_type = glColorTypeFromPngColorType(color_type);
glTexImage2D (
GL_TEXTURE_2D, 0, gl_color_type, // GL_RGBA8
width, height, 0, GL_RGBA,
GL_UNSIGNED_BYTE, data
);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
free(data);
*ptexture = texture_id;
return LOAD_TEXTURE__SUCCESS;
}

Related

SDL2 Camera Cutting Off Screen Edges

I'm trying to create a simple camera for my SDL2 platformer with C. However, whenever the player reaches the screen edges, it seems to be cut off by the background. Here is what the player looks like normally:
And here is what the player looks like when it reaches the screen edges:
To make the camera follow the player, I'm just creating a SDL_Rect called camera, setting it to the player x and y positions, and setting the viewport with SDL_RenderSetViewport to the camera rectangle.
Here's the code for that:
void handle_camera() {
SDL_Rect camera = {
.x = WIDTH/2 - player.x - BLOCK_SIZE/2,
.y = HEIGHT/2 - player.y - BLOCK_SIZE/2,
.w = WIDTH,
.h = HEIGHT
};
SDL_RenderSetViewport(game.renderer, &camera);
}
Therefore, I was wondering: what's wrong with my camera function and why is the player being cut off when it gets near the screen edges?
Here is the full code if needed (I organized in functions so I hope it's not too hard to understand):
#include <stdio.h>
#include <stdbool.h>
#include <SDL2/SDL.h>
#define WIDTH 1200
#define HEIGHT 800
#define BLOCK_SIZE 50
#define PLATFORM_AMOUNT 11 //This makes sure there are enough iterations of the loop, and also allocates enough memory for the 2D array of platforms.
#define LAVA_AMOUNT 2
#define TRAMPOLINE_AMOUNT 1
//Prototyping Functions
int initialize();
void handle_input();
void draw_player();
void player_moveX();
void player_moveY();
void checkCollisionsX();
void checkCollisionsY();
int rectCollide();
void drawLevel();
void resetPlayer();
void handle_camera();
typedef struct {
SDL_Renderer *renderer;
SDL_Window *window;
SDL_Surface *surface;
bool running;
int FPS;
bool close_requested;
int input[256];
} Game;
Game game = {
.running = true,
.FPS = 80,
.close_requested = false,
.input = {},
};
typedef struct {
int x;
int y;
double x_vel;
double y_vel;
double x_acc;
double y_acc;
int width;
int height;
double accSpeed;
int maxVel;
double gravity;
double friction;
double jumpForce;
double canJump;
} Player;
Player player = {
.y = HEIGHT-(BLOCK_SIZE*2),
.x = BLOCK_SIZE,
.x_vel = 0,
.y_vel = 0,
.x_acc = 0,
.y_acc = 0,
.width = BLOCK_SIZE,
.height = BLOCK_SIZE,
.accSpeed = 0.15,
.maxVel = 7,
.gravity = 0.5,
.friction = 0.15,
.jumpForce = 15,
.canJump = true,
};
int platforms[PLATFORM_AMOUNT][4] = {
{0, 0, BLOCK_SIZE, HEIGHT}, //WALLS
{0, HEIGHT-BLOCK_SIZE, WIDTH, BLOCK_SIZE},
{400-BLOCK_SIZE, HEIGHT-(BLOCK_SIZE*2), BLOCK_SIZE, BLOCK_SIZE}, //RAMP TO LAVA
{400-BLOCK_SIZE, HEIGHT-(BLOCK_SIZE*3), BLOCK_SIZE, BLOCK_SIZE},
{300, HEIGHT-(BLOCK_SIZE*2), BLOCK_SIZE, BLOCK_SIZE},
{800, HEIGHT-(BLOCK_SIZE*2), BLOCK_SIZE, BLOCK_SIZE},
{800, HEIGHT-(BLOCK_SIZE*3), BLOCK_SIZE, BLOCK_SIZE},
{800+BLOCK_SIZE, HEIGHT-(BLOCK_SIZE*2), BLOCK_SIZE, BLOCK_SIZE},
{WIDTH-BLOCK_SIZE*10, HEIGHT-(BLOCK_SIZE*8), BLOCK_SIZE, BLOCK_SIZE}, //Blocks above lava
{WIDTH-BLOCK_SIZE*8, HEIGHT-(BLOCK_SIZE*10), BLOCK_SIZE, BLOCK_SIZE},
{BLOCK_SIZE, BLOCK_SIZE*3, BLOCK_SIZE*9, BLOCK_SIZE}, //Top platform
};
int lava[LAVA_AMOUNT][4] = {
{400, HEIGHT-(BLOCK_SIZE*3), 400, BLOCK_SIZE*2},
{BLOCK_SIZE*4, BLOCK_SIZE*2, BLOCK_SIZE*3, BLOCK_SIZE},
};
int trampoline[TRAMPOLINE_AMOUNT][4] = {
{WIDTH/2-(BLOCK_SIZE/2), HEIGHT-(BLOCK_SIZE*5), BLOCK_SIZE, BLOCK_SIZE}
};
int main() {
initialize();
while(game.running && !game.close_requested) { //Game loop
SDL_SetRenderDrawColor(game.renderer, 181, 247, 255, 255);
SDL_RenderClear(game.renderer);
handle_input();
handle_camera();
//Collisions only work in this order: playerMoveX, checkCollisionsX, playerMoveY, checkCollisionsY. Then you can draw the platforms and the player.
player_moveX();
checkCollisionsX();
player_moveY();
checkCollisionsY();
drawLevel();
draw_player();
SDL_RenderPresent(game.renderer);
SDL_Delay(1000/game.FPS);
} //End of game loop
SDL_DestroyRenderer(game.renderer);
SDL_DestroyWindow(game.window);
SDL_Quit();
return 0;
}
int initialize() {
if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER) != 0) { //return 0 on success
printf("error initializing SDL: %s\n", SDL_GetError());
return 1;
}
game.window = SDL_CreateWindow("Sam's Platformer", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, WIDTH, HEIGHT, SDL_WINDOW_RESIZABLE); //creates window
if (!game.window) {
printf("error creating window: %s\n", SDL_GetError());
SDL_Quit();
return 1;
}
Uint32 render_flags = SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC; //creates a renderer
game.renderer = SDL_CreateRenderer(game.window, -1, render_flags);
if (!game.renderer) {
printf("error creating renderer: %s\n", SDL_GetError());
SDL_DestroyWindow(game.window);
SDL_Quit();
return 1;
}
return 0;
}
void handle_input() {
SDL_Event event;
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
game.close_requested = true;
game.running = false;
}
//printf("input: %p code: %i\n", game.input, event.key.keysym.scancode);
if (event.type == SDL_KEYDOWN) {
game.input[event.key.keysym.scancode] = true;
//printf("True");
}
if (event.type == SDL_KEYUP) {
game.input[event.key.keysym.scancode] = false;
//printf("False");
}
}
if (game.input[SDL_SCANCODE_R]) {
resetPlayer();
}
}
void draw_player() {
SDL_Rect playerRect = {
.x = player.x,
.y = player.y,
.w = player.width,
.h = player.height
};
SDL_SetRenderDrawColor(game.renderer, 0, 200, 50, 255);
SDL_RenderFillRect(game.renderer, &playerRect);
}
void resetPlayer() {
player.y = HEIGHT-(BLOCK_SIZE*2);
player.x = BLOCK_SIZE;
player.x_vel = 0;
player.y_vel = 0;
}
void player_moveX() {
if (game.input[SDL_SCANCODE_LEFT] && player.x_vel > -player.maxVel) {
player.x_acc = -player.accSpeed;
} else if (game.input[SDL_SCANCODE_RIGHT] && player.x_vel < player.maxVel) {
player.x_acc = player.accSpeed;
} else if (abs(player.x_vel) > 0.2) {
if (player.x_vel < 0) {
player.x_acc = player.friction;
} else {
player.x_acc = -player.friction;
}
} else {
player.x_vel = 0;
player.x_acc = 0;
}
player.x_vel += player.x_acc;
player.x += player.x_vel;
}
void player_moveY() {
if (game.input[SDL_SCANCODE_UP] && player.y_vel == 0 && player.y_acc == 0 && player.canJump) {
player.canJump = false;
player.y_vel = -player.jumpForce;
}
player.y_acc += player.gravity;
player.y_vel += player.y_acc;
player.y += player.y_vel;
player.y_acc = 0;
}
void checkCollisionsX() {
for (int i = 0; i < PLATFORM_AMOUNT; i++) {
if (rectCollide(player.x, player.y, BLOCK_SIZE, BLOCK_SIZE, platforms[i][0], platforms[i][1], platforms[i][2], platforms[i][3])) {
if (player.x_vel < 0) { // If the player moved left and collided with the right side of block
player.x = platforms[i][0] + platforms[i][2];
} else { // If the player moved right and collided with the left side of block
player.x = platforms[i][0] - player.width;
}
player.x_vel = 0;
}
}
/*if (player.x >= WIDTH - player.width) {
player.x = WIDTH - player.width;
player.x_vel = 0;
}*/
for (int i = 0; i < LAVA_AMOUNT; i++) {
if (rectCollide(player.x, player.y, BLOCK_SIZE, BLOCK_SIZE, lava[i][0], lava[i][1], lava[i][2], lava[i][3])) {
resetPlayer();
}
}
for (int i = 0; i < TRAMPOLINE_AMOUNT; i++) {
if (rectCollide(player.x, player.y, BLOCK_SIZE, BLOCK_SIZE, trampoline[i][0], trampoline[i][1], trampoline[i][2], trampoline[i][3])) {
if (player.x_vel < 0) { // If the player moved left and collided with the right side of block
player.x = trampoline[i][0] + trampoline[i][2];
} else { // If the player moved right and collided with the left side of block
player.x = trampoline[i][0] - player.width;
}
player.x_vel = 0;
}
}
}
void checkCollisionsY() {
for (int i = 0; i < PLATFORM_AMOUNT; i++) {
if (rectCollide(player.x, player.y, player.width, player.height, platforms[i][0], platforms[i][1], platforms[i][2], platforms[i][3])) {
if (player.y_vel < 0) { // If the player hit their head
player.y = platforms[i][1] + platforms[i][3];
player.y_vel *= -0.5; // Not -1 because collisions are not perfectly elastic
} else {
player.y = platforms[i][1] - player.height;
player.y_vel = 0;
player.y_acc = 0;
player.canJump = true;
}
}
if (player.y >= HEIGHT - player.height) {
player.y_vel = 0;
player.y = HEIGHT - player.height;
if (!game.input[SDL_SCANCODE_UP]) {
player.canJump = true;
}
}
}
for (int i = 0; i < LAVA_AMOUNT; i++) {
if (rectCollide(player.x, player.y, BLOCK_SIZE, BLOCK_SIZE, lava[i][0], lava[i][1], lava[i][2], lava[i][3])) {
resetPlayer();
}
}
for (int i = 0; i < TRAMPOLINE_AMOUNT; i++) {
if (rectCollide(player.x, player.y, BLOCK_SIZE, BLOCK_SIZE, trampoline[i][0], trampoline[i][1], trampoline[i][2], trampoline[i][3])) {
if (player.y_vel < 0) { // If the player hit their head
player.y = trampoline[i][1] + trampoline[i][3];
player.y_vel *= -0.5; // Not -1 because collisions are not perfectly elastic
} else {
player.y = trampoline[i][1] - trampoline[i][3];
player.y_vel = -player.y_vel;
}
}
}
}
int rectCollide(int x1, int y1, int w1, int h1, int x2,int y2, int w2, int h2) {
return x1 + w1 > x2 && x1 < x2 + w2 && y1 + h1 > y2 && y1 < y2 + h2;
}
void drawLevel() {
for (int i = 0; i < PLATFORM_AMOUNT; i++) {
SDL_Rect platform = {platforms[i][0], platforms[i][1], platforms[i][2], platforms[i][3]};
SDL_SetRenderDrawColor(game.renderer, 156, 104, 0, 255);
SDL_RenderFillRect(game.renderer, &platform);
}
for (int i = 0; i < LAVA_AMOUNT; i++) {
int lavaRedColor = 255;
SDL_Rect lavaBlock = {lava[i][0], lava[i][1], lava[i][2], lava[i][3]};
SDL_SetRenderDrawColor(game.renderer, lavaRedColor, 0, 0, 255);
SDL_RenderFillRect(game.renderer, &lavaBlock);
}
for (int i = 0; i < TRAMPOLINE_AMOUNT; i++) {
SDL_Rect trampolineBlock = {trampoline[i][0], trampoline[i][1], trampoline[i][2], trampoline[i][3]};
SDL_SetRenderDrawColor(game.renderer, 235, 52, 229, 255);
SDL_RenderFillRect(game.renderer, &trampolineBlock);
}
}
void handle_camera() {
SDL_Rect camera = {
.x = WIDTH/2 - player.x - BLOCK_SIZE/2,
.y = HEIGHT/2 - player.y - BLOCK_SIZE/2,
.w = WIDTH, //Screen width
.h = HEIGHT //Screen height
};
SDL_RenderSetViewport(game.renderer, &camera);
}
Thanks for any help.
https://gamedev.stackexchange.com/questions/121421/how-to-use-the-sdl-viewport-properly
See this related post. Essentially changing the SDL viewport is not the way you'd typically handle an in game camera. You need to consider drawing your in game entities (level objects etc.) relative to the camera.

My code won't display sprite SDL2

The screen is always black. Tell me how to display the sprites correctly.
This is my code:
#define SHAPE_SIZE 32
void aff_map(SDL_Renderer *renderer)
{
SDL_Surface *img;
SDL_Texture *Tfloor
int x = 0;
int y = 0;
int map[4][8] = {{0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0}};
SDL_Rect SrcR;
SDL_Rect DestR;
DestR.x = 0;
DestR.y = 0;
DestR.w = SHAPE_SIZE;
DestR.h = SHAPE_SIZE;
img = IMG_Load("floor.bmp");
Tfloor = SDL_CreateTextureFromSurface(renderer, img);
while (y < 4)
{
x = 0;
while (x < 8)
{
if (map[y][x] == 0)
SDL_RenderCopy(renderer, Tfloor, NULL, &DestR);
x++;
DestR.x = DestR.x + 32;
}
DestR.x = 0;
DestR.y = DestR.y + 32;
y++;
}
SDL_RenderPresent(renderer);
}
int main()
{
SDL_Window *screen;
SDL_Event evenements;
SDL_Renderer *renderer;
screen = SDL_CreateWindow("Zappy", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 8 * SHAPE_SIZE -32, 4 * SHAPE_SIZE, 0);
renderer = SDL_CreateRenderer(screen, -1, SDL_RENDERER_ACCELERATED);
SDL_RenderClear(renderer);
while (42)
{
SDL_WaitEvent(&evenements);
if (evenements.window.event == SDL_WINDOWEVENT_CLOSE ||
evenements.key.keysym.sym == SDLK_ESCAPE)
{
SDL_DestroyWindow(screen);
SDL_Quit();
break;
}
aff_map(renderer);
}
return 0;
}
The error message is explicit.
It says that the "floor.bmp" has not been converted to a surface.
It means that 'img' parameter is NULL.
Try the following :
Specify the full path to your picture in IMG_Load(), for example "/home/quentin/floor.bmp"
Check the return value of IMG_Load().

How to load and fill cubes with texture image in openGL

I have a grid with cubes and i want to fill the cubes with two different colors and with 3 different images(.bmp). So every cube is filled with colours or images.
I wrote a code and when i press the <> button the grid is filled with 5 different colours. Can anyone tell me how can i change my code to fill the grid with 3 different images(randomly)?
Here is my code:
void randomFilling();
void myprint();
struct square{
int v1x, v1y;
int v2x, v2y;
int v3x, v3y;
int v4x, v4y;
int color;
};
struct square Squares[12][15];
struct flags{
int b;
}flags;
void drawScene();
void findVerticesPosition(){
int counter=0;
for(int i=0; i<600; i+=40){
for(int j=0; j<480; j+=40){
Squares[j/40][i/40].v1x = i;
Squares[j/40][i/40].v1y = j;
Squares[j/40][i/40].v2x = i;
Squares[j/40][i/40].v2y = j+40;
Squares[j/40][i/40].v3x = i+40;
Squares[j/40][i/40].v3y = j+40;
Squares[j/40][i/40].v4x = i+40;
Squares[j/40][i/40].v4y = j;
}
}
for(int i=0; i<12; i++){
for(int j=0; j<15; j++){
Squares[i][j].color = rand()%5 + 1;
}
}
}
void handleKeypress(unsigned char key, int x, int y) {
switch (key) {
case 27: //Escape key
exit(0);
case 98: //b
randomFilling();
flags.b = 1;
drawScene();
}
}
void randomFilling(){
int randomNumber;
srand(time(NULL));
//randomNumber = rand() % 5 + 1;
for(int i=0; i<12; i++){
for(int j=0; j<15; j++){
randomNumber = Squares[i][j].color;
if(randomNumber == 1){
glBegin(GL_QUADS);
glColor3f(1.0,0.9,0.1);
glVertex2f(Squares[i][j].v1x, Squares[i][j].v1y);
glVertex2f(Squares[i][j].v2x, Squares[i][j].v2y);
glVertex2f(Squares[i][j].v3x, Squares[i][j].v3y);
glVertex2f(Squares[i][j].v4x, Squares[i][j].v4y);
glEnd();
}
else if(randomNumber == 2){
glBegin(GL_QUADS);
glColor3f(1.0,0.0,0.1);
glVertex2f(Squares[i][j].v1x, Squares[i][j].v1y);
glVertex2f(Squares[i][j].v2x, Squares[i][j].v2y);
glVertex2f(Squares[i][j].v3x, Squares[i][j].v3y);
glVertex2f(Squares[i][j].v4x, Squares[i][j].v4y);
glEnd();
}
else if(randomNumber == 3){
glBegin(GL_QUADS);
glColor3f(0,0.9,0.1);
glVertex2f(Squares[i][j].v1x, Squares[i][j].v1y);
glVertex2f(Squares[i][j].v2x, Squares[i][j].v2y);
glVertex2f(Squares[i][j].v3x, Squares[i][j].v3y);
glVertex2f(Squares[i][j].v4x, Squares[i][j].v4y);
glEnd();
}
else if(randomNumber == 4){
glBegin(GL_QUADS);
glColor3f(0,0,1);
glVertex2f(Squares[i][j].v1x, Squares[i][j].v1y);
glVertex2f(Squares[i][j].v2x, Squares[i][j].v2y);
glVertex2f(Squares[i][j].v3x, Squares[i][j].v3y);
glVertex2f(Squares[i][j].v4x, Squares[i][j].v4y);
glEnd();
}
else if(randomNumber == 5){
glBegin(GL_QUADS);
glColor3f(0,0.9,1);
glVertex2f(Squares[i][j].v1x, Squares[i][j].v1y);
glVertex2f(Squares[i][j].v2x, Squares[i][j].v2y);
glVertex2f(Squares[i][j].v3x, Squares[i][j].v3y);
glVertex2f(Squares[i][j].v4x, Squares[i][j].v4y);
glEnd();
}
else{
printf("WTF\n");
}
}
}
}
//Initialize OpenGL
void init(void) {
glClearColor(1.0,1.0,1.0,1.0);
glMatrixMode(GL_PROJECTION);
gluOrtho2D(0.0,600.0,-60.0,480.0);
flags.b=0;
}
void drawScene(void) {
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(0.0,0.0,0.0);
//glPointSize(3.0);
if(flags.b==1){
randomFilling(); //------------
}
glColor3f(0,0,0);
glBegin(GL_LINES);
for(int i = 0; i <= 600; i += 40)
{
glVertex2f((float)i, 0.0f);
glVertex2f((float)i, 480.0f);
glVertex2f(0.0f, (float)i);
glVertex2f(600.0f, (float)i);
}
glEnd();
glFlush();
}
int main(int argc, char**argv) {
findVerticesPosition();
//myprint();
glutInit(&argc, argv);
glutInitWindowPosition(300,80);
glutInitWindowSize(600,540);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutCreateWindow("BraXaPsa II");
init();
glutDisplayFunc(drawScene);
//glutDisplayFunc(randomFilling);
glutKeyboardFunc(handleKeypress);
glutMainLoop();
}
Here I post code to display images(textures) instead of colors.
// relative path to texture bitmaps
char* texture_names[] = {
"textures\\grass.tga",
"textures\\wood\\brown wood.tga",
"textures\\ceiling.tga"
};
void randomFilling();
void myprint();
struct square{
int v1x, v1y;
int v2x, v2y;
int v3x, v3y;
int v4x, v4y;
int texture;
};
struct square Squares[12][15];
struct flags{
int b;
}flags;
void drawScene();
void findVerticesPosition(){
int counter=0;
for(int i=0; i<600; i+=40){
for(int j=0; j<480; j+=40){
Squares[j/40][i/40].v1x = i;
Squares[j/40][i/40].v1y = j;
Squares[j/40][i/40].v2x = i;
Squares[j/40][i/40].v2y = j+40;
Squares[j/40][i/40].v3x = i+40;
Squares[j/40][i/40].v3y = j+40;
Squares[j/40][i/40].v4x = i+40;
Squares[j/40][i/40].v4y = j;
}
}
for(int i=0; i<12; i++){
for(int j=0; j<15; j++){
Squares[i][j].texture = rand()%3;
}
}
}
void handleKeypress(unsigned char key, int x, int y) {
switch (key) {
case 27: //Escape key
exit(0);
case 98: //b
randomFilling();
flags.b = 1;
drawScene();
}
}
// creating texture objects array
GLuint g_pnTextures[3];
void randomFilling(){
for(int i=0; i<12; i++){
for(int j=0; j<15; j++){
glColor3f(1.0f, 1.0f, 1.0f);
glBindTexture(GL_TEXTURE_2D, g_pnTextures[Squares[i][j].texture]);
glBegin(GL_QUADS);
// specify texture coords
glTexCoord2f(0.0f, 0.0f);
glVertex2f(Squares[i][j].v1x, Squares[i][j].v1y);
// specify texture coords
glTexCoord2f(0.0f, 1.0f);
glVertex2f(Squares[i][j].v2x, Squares[i][j].v2y);
// specify texture coords
glTexCoord2f(1.0f, 1.0f);
glVertex2f(Squares[i][j].v3x, Squares[i][j].v3y);
// specify texture coords
glTexCoord2f(1.0f, 0.0f);
glVertex2f(Squares[i][j].v4x, Squares[i][j].v4y);
glEnd();
}
}
}
//Initialize OpenGL
void init(void) {
GLbyte* pImage = NULL;
GLint width = 0;
GLint height = 0;
GLint components = 0;
GLenum format;
glClearColor(1.0,1.0,1.0,1.0);
glMatrixMode(GL_PROJECTION);
gluOrtho2D(0.0,600.0,-60.0,480.0);
flags.b=0;
// Generate texture object
glGenTextures(3, g_pnTextures);
for (int i = 0; i < 3; i++)
{
// bind current texture object
glBindTexture(GL_TEXTURE_2D,g_pnTextures[i]);
// load texture data
pImage = gltLoadTGA(texture_names[i],&width,&height,&components,&format);
glTexParameteri(GL_TEXTURE_2D,GL_GENERATE_MIPMAP,GL_TRUE);
printf("texture: \"%s\" - %p\n",texture_names[i],pImage);
// Load texture data to video memory
glTexImage2D(GL_TEXTURE_2D,0,GL_COMPRESSED_RGB_S3TC_DXT1_EXT,
width,height,0,format,GL_UNSIGNED_BYTE,pImage);
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_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_BASE_LEVEL,0);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAX_LEVEL,8);
glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_COMBINE);
glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB,GL_MODULATE);
delete [] pImage;
pImage = NULL;
}
glEnable(GL_TEXTURE_2D);
}
void drawScene(void) {
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(0.0,0.0,0.0);
//glPointSize(3.0);
if(flags.b==1){
randomFilling(); //------------
}
glColor3f(0,0,0);
glBegin(GL_LINES);
for(int i = 0; i <= 600; i += 40)
{
glVertex2f((float)i, 0.0f);
glVertex2f((float)i, 480.0f);
glVertex2f(0.0f, (float)i);
glVertex2f(600.0f, (float)i);
}
glEnd();
glFlush();
}
int main(int argc, char**argv) {
findVerticesPosition();
//myprint();
glutInit(&argc, argv);
glutInitWindowPosition(300,80);
glutInitWindowSize(600,540);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutCreateWindow("BraXaPsa II");
init();
glutDisplayFunc(drawScene);
//glutDisplayFunc(randomFilling);
glutKeyboardFunc(handleKeypress);
glutMainLoop();
// Unload texture data
glDeleteTextures(3, g_pnTextures);
}
The result will be like:
The two essential parts is to load textures to memory and specifying texture coordinates to primitives for proper texture wrapping.
Texture loading process is displayed here.
for (int i = 0; i < 3; i++)
{
// bind current texture object
glBindTexture(GL_TEXTURE_2D,g_pnTextures[i]);
// load texture data
pImage = gltLoadTGA(texture_names[i],&width,&height,&components,&format);
glTexParameteri(GL_TEXTURE_2D,GL_GENERATE_MIPMAP,GL_TRUE);
printf("texture: \"%s\" - %p\n",texture_names[i],pImage);
// Load texture data to video memory
glTexImage2D(GL_TEXTURE_2D,0,GL_COMPRESSED_RGB_S3TC_DXT1_EXT,
width,height,0,format,GL_UNSIGNED_BYTE,pImage);
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_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_BASE_LEVEL,0);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAX_LEVEL,8);
glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_COMBINE);
glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB,GL_MODULATE);
delete [] pImage;
pImage = NULL;
}
And texture coord maping process.
glBegin(GL_QUADS);
// specify texture coords
glTexCoord2f(0.0f, 0.0f);
glVertex2f(Squares[i][j].v1x, Squares[i][j].v1y);
// specify texture coords
glTexCoord2f(0.0f, 1.0f);
glVertex2f(Squares[i][j].v2x, Squares[i][j].v2y);
// specify texture coords
glTexCoord2f(1.0f, 1.0f);
glVertex2f(Squares[i][j].v3x, Squares[i][j].v3y);
// specify texture coords
glTexCoord2f(1.0f, 0.0f);
glVertex2f(Squares[i][j].v4x, Squares[i][j].v4y);
glEnd();
As you cannot load tga bitmaps directly. I post code to deal with this problem.
// Define targa header.
#pragma pack(1)
typedef struct
{
GLbyte identsize; // Size of ID field that follows header (0)
GLbyte colorMapType; // 0 = None, 1 = paletted
GLbyte imageType; // 0 = none, 1 = indexed, 2 = rgb, 3 = grey, +8=rle
unsigned short colorMapStart; // First colour map entry
unsigned short colorMapLength; // Number of colors
unsigned char colorMapBits; // bits per palette entry
unsigned short xstart; // image x origin
unsigned short ystart; // image y origin
unsigned short width; // width in pixels
unsigned short height; // height in pixels
GLbyte bits; // bits per pixel (8 16, 24, 32)
GLbyte descriptor; // image descriptor
} TGAHEADER;
#pragma pack(8)
GLbyte *gltLoadTGA(const char *szFileName, GLint *iWidth, GLint *iHeight, GLint *iComponents, GLenum *eFormat)
{
FILE *pFile; // File pointer
TGAHEADER tgaHeader; // TGA file header
unsigned long lImageSize; // Size in bytes of image
short sDepth; // Pixel depth;
GLbyte *pBits = NULL; // Pointer to bits
// Default/Failed values
*iWidth = 0;
*iHeight = 0;
*eFormat = GL_BGR_EXT;
*iComponents = GL_RGB8;
// Attempt to open the fil
pFile = fopen(szFileName, "rb");
if(pFile == NULL)
return NULL;
// Read in header (binary)
fread(&tgaHeader, 18/* sizeof(TGAHEADER)*/, 1, pFile);
// Do byte swap for big vs little endian
#ifdef __APPLE__
BYTE_SWAP(tgaHeader.colorMapStart);
BYTE_SWAP(tgaHeader.colorMapLength);
BYTE_SWAP(tgaHeader.xstart);
BYTE_SWAP(tgaHeader.ystart);
BYTE_SWAP(tgaHeader.width);
BYTE_SWAP(tgaHeader.height);
#endif
// Get width, height, and depth of texture
*iWidth = tgaHeader.width;
*iHeight = tgaHeader.height;
sDepth = tgaHeader.bits / 8;
// Put some validity checks here. Very simply, I only understand
// or care about 8, 24, or 32 bit targa's.
if(tgaHeader.bits != 8 && tgaHeader.bits != 24 && tgaHeader.bits != 32)
return NULL;
// Calculate size of image buffer
lImageSize = tgaHeader.width * tgaHeader.height * sDepth;
// Allocate memory and check for success
pBits = new GLbyte[lImageSize];
if(pBits == NULL)
return NULL;
// Read in the bits
// Check for read error. This should catch RLE or other
// weird formats that I don't want to recognize
if(fread(pBits, lImageSize, 1, pFile) != 1)
{
free(pBits);
return NULL;
}
// Set OpenGL format expected
switch(sDepth)
{
case 3: // Most likely case
*eFormat = GL_BGR_EXT;
*iComponents = GL_RGB8;
break;
case 4:
*eFormat = GL_BGRA_EXT;
*iComponents = GL_RGBA8;
break;
case 1:
*eFormat = GL_LUMINANCE;
*iComponents = GL_LUMINANCE8;
break;
};
// Done with File
fclose(pFile);
// Return pointer to image data
return pBits;
}

Create a eglpbuffersurface and bind it to eglwindowsurface [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
/*
This Code draws a rectangle on eglwindowsurface , however intention is to draw on pbuffersurface which would be binded to eglwindowsurface
*/
static void _subset_Rectf(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2,
GLfloat r, GLfloat g, GLfloat b)
{
GLfloat v[4][2], c[4][4];
int i;
v[0][0] = x1; v[0][1] = y1;
v[1][0] = x2; v[1][1] = y1;
v[2][0] = x2; v[2][1] = y2;
v[3][0] = x1; v[3][1] = y2;
for (i = 0; i < 4; i++) {
c[i][0] = r;
c[i][1] = g;
c[i][2] = b;
c[i][3] = 1.0;
}
glVertexPointer(2, GL_FLOAT, 0, v);
glColorPointer(4, GL_FLOAT, 0, v);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
}
/*
redraw call swaps the buffers and calls draw rectangle
*/
static void redraw(EGLDisplay dpy, EGLSurface surf, int rot)
{
GLfloat r, g, b;
glClearColor(rand()/(float)RAND_MAX,
rand()/(float)RAND_MAX,
rand()/(float)RAND_MAX,
1);
glClear( GL_COLOR_BUFFER_BIT );
r = rand()/(float)RAND_MAX;
g = rand()/(float)RAND_MAX;
b = rand()/(float)RAND_MAX;
glPushMatrix();
glRotatef(rot, 0, 0, 1);
glScalef(.5, .5, .5);
_subset_Rectf( -1, -1, 1, 1, r, g, b );
glPopMatrix();
eglSwapBuffers( dpy, surf );
glFinish();
}
/*main functtion*/
int main(int argc, char *argv[])
{
int maj, min;
EGLContext ctx;
EGLSurface pbuffer, screen_surf;
EGLConfig configs[10];
EGLint numConfigs, i;
EGLBoolean b;
const EGLint pbufAttribs[] = {
EGL_WIDTH, 500,
EGL_HEIGHT, 500,
EGL_NONE
};
const EGLint screenAttribs[] = {
EGL_WIDTH, 1024,
EGL_HEIGHT, 768,
EGL_NONE
};
Window window;
Display *display;
if(!(display=XOpenDisplay(NULL))) {
fprintf(stderr, "rsadhu::ERROR: Could not open display\n");
exit(1);
}
Colormap colormap;
XVisualInfo *pVisual;
EGLint count;
EGLDisplay d = eglGetDisplay(display);
assert(d);
if (!eglInitialize(d, &maj, &min)) {
printf("rsadhu:: demo: eglInitialize failed\n");
exit(1);
}
eglGetConfigs(d, configs, 10, &numConfigs);
for (i = 0; i < numConfigs; i++) {
EGLint id, red, depth;
eglGetConfigAttrib(d, configs[i], EGL_CONFIG_ID, &id);
eglGetConfigAttrib(d, configs[i], EGL_RED_SIZE, &red);
eglGetConfigAttrib(d, configs[i], EGL_DEPTH_SIZE, &depth);
printf("rsadhu:: %2d: Red Size = %d Depth Size = %d\n", id, red, depth);
}
ctx = eglCreateContext(d, configs[0], EGL_NO_CONTEXT, NULL);
if (ctx == EGL_NO_CONTEXT) {
return 0;
}
window = CreateWindow("OpenGL ES 2.0 DRI", SIZEX, SIZEY, display, d,configs[0], &colormap, &pVisual); // creates an X Window
pbuffer = eglCreatePbufferSurface(d, configs[0], pbufAttribs);
if (pbuffer == EGL_NO_SURFACE) {
printf("rsadhu:: failed to create pbuffer\n");
return 0;
}
b = eglMakeCurrent(d, pbuffer, pbuffer, ctx);
if (!b) {
printf("rsadhu::make current failed\n");
return 0;
}
b = eglMakeCurrent(d, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
screen_surf = eglCreateWindowSurface(d,configs[0],(NativeWindowType)window,NULL);;
if (screen_surf == EGL_NO_SURFACE) {
printf("rsadhu::failed to create screen surface\n");
return 0;
}
b = eglMakeCurrent(d, screen_surf, screen_surf, ctx);
if (!b) {
printf("rsadhu::make current failed\n");
return 0;
}
glViewport(0, 0, 1024, 768);
glClearColor(0, 1.0, 0, 1);
glClear( GL_COLOR_BUFFER_BIT );
glShadeModel( GL_FLAT );
while(1)
{
static int frames = 0;
static double timeLast = GetCurrentTimeInSeconds();
double timeCurrent = GetCurrentTimeInSeconds();
redraw(d, screen_surf, i*10 ); // MAIN CAL ....
frames++;
if (timeCurrent - timeLast >= 1.0) {
GLfloat seconds = timeCurrent - timeLast;
GLfloat fps = frames / seconds;
printf("rsadhu :: %d frames in %3.1f seconds = %6.3f FPS\n", frames, seconds,fps);
timeLast = timeCurrent;
frames = 0;
}
}
eglDestroySurface(d, pbuffer);
eglDestroyContext(d, ctx);
eglTerminate(d);
return 0;
}
Is there any reason why you would want to use pbuffers still ? If your objective is to render to offscreen buffer, and bind it as texture for rendering to display, Frame Buffer Object (FBO) can be used instead and is more efficient. You can refer to discussion in opengl forum here. You can refer to code for setting up FBO in a simple manner from here sgxperf code gist
By the way, your code will render to display buffer only because you have made screen_surf the latest current surface in the eglMakeCurrent call.

Get pixel color at mouse position fastest way

So actually i got a very fast and nice code from "Vodemki" in here -
Get Pixel color fastest way?
But only problem it scans the whole image while i need to scan only
my current mouse position
Here's the code -
HDC hdc, hdcTemp;
RECT rect;
BYTE* bitPointer;
int x, y;
int red, green, blue, alpha;
while(true)
{
hdc = GetDC(HWND_DESKTOP);
GetWindowRect(hWND_Desktop, &rect);
int MAX_WIDTH = rect.right;
int MAX_HEIGHT = rect.bottom;
hdcTemp = CreateCompatibleDC(hdc);
BITMAPINFO bitmap;
bitmap.bmiHeader.biSize = sizeof(bitmap.bmiHeader);
bitmap.bmiHeader.biWidth = MAX_WIDTH;
bitmap.bmiHeader.biHeight = MAX_HEIGHT;
bitmap.bmiHeader.biPlanes = 1;
bitmap.bmiHeader.biBitCount = 32;
bitmap.bmiHeader.biCompression = BI_RGB;
bitmap.bmiHeader.biSizeImage = MAX_WIDTH * 4 * MAX_HEIGHT;
bitmap.bmiHeader.biClrUsed = 0;
bitmap.bmiHeader.biClrImportant = 0;
HBITMAP hBitmap2 = CreateDIBSection(hdcTemp, &bitmap, DIB_RGB_COLORS, (void**)(&bitPointer), NULL, NULL);
SelectObject(hdcTemp, hBitmap2);
BitBlt(hdcTemp, 0, 0, MAX_WIDTH, MAX_HEIGHT, hdc, 0, 0, SRCCOPY);
for (int i=0; i<(MAX_WIDTH * 4 * MAX_HEIGHT); i+=4)
{
red = (int)bitPointer[i];
green = (int)bitPointer[i+1];
blue = (int)bitPointer[i+2];
alpha = (int)bitPointer[i+3];
x = i / (4 * MAX_HEIGHT);
y = i / (4 * MAX_WIDTH);
if (red == 255 && green == 0 && blue == 0)
{
SetCursorPos(x,y);
mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
Sleep(50);
mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
Sleep(25);
}
}
}
I'm not familiar with BitBlt, So if anyone can help me modify that code i'll appreciate it
Thanks!
Alright I made it finally.
I still got problem with the timing, makes my puter very slow...
I'll work for it later...
Here's the code -
//Globals
int sX, sY, x, y;
BYTE* sData = 0;
POINT cursorPos;
HDC hScreen;
HDC hdcMem;
HBITMAP hBitmap;
HGDIOBJ hOld;
void PixelFunction(); // Get the pixel rgb function
int main()
{
PixelFunction();
ReleaseDC(NULL, hScreen);
DeleteDC(hdcMem);
return 0;
}
void PixelFunction()
{
int Red, Green, Blue;
hScreen = GetDC(NULL);
sX = GetDeviceCaps(hScreen, HORZRES);
sY = GetDeviceCaps(hScreen, VERTRES);
hdcMem = CreateCompatibleDC (hScreen);
hBitmap = CreateCompatibleBitmap(hScreen, sX, sY);
BITMAPINFOHEADER bm = {0};
bm.biSize = sizeof(BITMAPINFOHEADER);
bm.biPlanes = 1;
bm.biBitCount = 32;
bm.biWidth = sX;
bm.biHeight = -sY;
bm.biCompression = BI_RGB;
bm.biSizeImage = 0; // 3 * sX * sY;
while (1) {
hOld = SelectObject(hdcMem, hBitmap);
BitBlt(hdcMem, 0, 0, sX, sY, hScreen, 0, 0, SRCCOPY);
SelectObject(hdcMem, hOld);
free(sData);
sData = (BYTE*)malloc(4 * sX * sY);
GetDIBits(hdcMem, hBitmap, 0, sY, sData, (BITMAPINFO*)&bm, DIB_RGB_COLORS);
GetCursorPos(&cursorPos);
x = cursorPos.x;
y = cursorPos.y;
Red = sData[4 * ( (y * sX) + x) +2];
Green = sData[4 * ( ( y * sX) + x) +1];
Blue = sData[4 * ( (y * sX) + x)];
// Check for color
if (Red == 255 && Green == 0 && Blue == 0) {
mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
Sleep(5);
mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
}
Sleep(10);
}
}
Hope it helped!

Resources