adding texture loading.

This commit is contained in:
Andreas Ortmann 2016-10-03 20:12:09 +02:00
parent 7eac02328d
commit dfda49c027
7 changed files with 252 additions and 5 deletions

View file

@ -6,10 +6,10 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules")
function(setup_target NAME)
set_property(TARGET ${NAME} PROPERTY CXX_STANDARD 14)
set_property(TARGET ${NAME} PROPERTY CXX_STANDARD_REQUIRED ON)
#target_compile_options(${NAME} PRIVATE -Wall -Wextra)
#target_compile_options(${NAME} PRIVATE -fdiagnostics-color=always)
#target_compile_options(${NAME} PRIVATE $<$<CONFIG:DEBUG>:-ggdb -O2>)
#target_compile_options(${NAME} PRIVATE $<$<CONFIG:RELEASE>:-O3 -NDEBUG>)
target_compile_options(${NAME} PRIVATE -Wall -Wextra)
target_compile_options(${NAME} PRIVATE -fdiagnostics-color=always)
target_compile_options(${NAME} PRIVATE $<$<CONFIG:DEBUG>:-ggdb -O2>)
target_compile_options(${NAME} PRIVATE $<$<CONFIG:RELEASE>:-O3 -NDEBUG>)
endfunction(setup_target)
add_subdirectory(game)

View file

@ -4,6 +4,7 @@ find_package(OpenGL REQUIRED)
find_package(epoxy REQUIRED)
find_package(X11 REQUIRED)
find_package(assimp REQUIRED)
find_package(PNG REQUIRED)
set(GAME_SRC
main.cpp
@ -11,10 +12,14 @@ set(GAME_SRC
glclasses.cpp
game_window.cpp
renderer.cpp
renderer_polygon_2d/renderer_polygon_2d.cpp
renderer_polygon_3d/renderer_polygon_3d.cpp
renderer_polygon_3d/polygon_model.cpp
renderer_polygon_3d/particle_batch.cpp
renderer_polygon_3d/image_texture.cpp
renderer_ray_tracer/renderer_ray_tracer.cpp
network/session.cpp
@ -45,6 +50,7 @@ set(GAME_SRC ${GAME_SRC} sound/dummy_sound.cpp)
include_directories(${CMAKE_CURRENT_BINARY_DIR})
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
include_directories(${OPENGL_INCLUDE_DIR})
include_directories(${PNG_INCLUDE_DIR})
include_directories(${CMAKE_SOURCE_DIR}/libs/glm/)
include_directories(${CMAKE_SOURCE_DIR}/libs/asio/asio/include/)
include_directories(${assimp_INCLUDE_DIRS})
@ -52,4 +58,5 @@ include_directories(${assimp_INCLUDE_DIRS})
add_executable(game ${GAME_SRC})
setup_target(game)
target_link_libraries(game X11 epoxy pthread ${assimp_LIBRARIES} assimp ${SOUND_LIBRARIES})
target_link_libraries(game X11 epoxy pthread ${assimp_LIBRARIES} assimp
${SOUND_LIBRARIES} ${PNG_LIBRARIES})

View file

@ -0,0 +1,161 @@
#include "image_texture.hpp"
#include <png.h>
#include <cmath>
namespace endofthejedi {
bool ImageTexture::loadPng()
{
m_valid = false;
//header for testing if it is a png
png_byte header[8];
//open file as binary
FILE *fp = fopen(m_path.c_str(), "rb");
if (!fp) {
printf("[image_texture] warning: could not open png file to load: %s\n", m_path.c_str());
return false;
}
//read the header
fread(header, 1, 8, fp);
//test if png
int is_png = !png_sig_cmp(header, 0, 8);
if (!is_png) {
puts("warning: image loader: file is not PNG!");
fclose(fp);
return false;
}
//create png struct
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!png_ptr) {
fclose(fp);
return false;
}
//create png info struct
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);
fclose(fp);
return false;
}
//create png info struct
png_infop end_info = png_create_info_struct(png_ptr);
if (!end_info) {
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL);
fclose(fp);
return false;
}
//png error stuff, not sure libpng man suggests this.
if (setjmp(png_jmpbuf(png_ptr))) {
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
fclose(fp);
return false;
}
//init png reading
png_init_io(png_ptr, fp);
//let libpng know you already read the first 8 bytes
png_set_sig_bytes(png_ptr, 8);
// read all the info up to the image data
png_read_info(png_ptr, info_ptr);
//variables to pass to get info
int bit_depth, color_type;
png_uint_32 twidth, theight;
// get info about png
png_get_IHDR(png_ptr, info_ptr, &twidth, &theight, &bit_depth, &color_type,
NULL, NULL, NULL);
//update width and height based on png info
m_width = twidth;
m_height = theight;
int pot_width = (int) pow(2, ceilf(log2f(m_width)));
int pot_height = (int) pow(2, ceilf(log2f(m_height)));
m_uv_scale_x = m_width / (float) pot_width;
m_uv_scale_y = m_height / (float) pot_height;
/*puts("#########################################");*/
/*printf("# PNG: width=%d, height=%d\n", width, height);*/
/*printf("# powers of two: w=%d, h=%d\n", pot_width, pot_height);*/
/*puts("#########################################");*/
// Update the png info struct.
png_read_update_info(png_ptr, info_ptr);
// Row size in bytes.
int rowbytes = png_get_rowbytes(png_ptr, info_ptr);
int pot_rowbytes = 4 * (int) pow(2, ceilf(log2f(rowbytes/4)));
/*printf("rowbytes: %d, pot_rowbytes=%d\n", rowbytes, pot_rowbytes);*/
// Allocate the image_data as a big block, to be given to opengl
png_byte *image_data = (png_byte *) calloc(pot_rowbytes * pot_height, sizeof(png_byte));
if (!image_data) {
//clean up memory and close stuff
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
fclose(fp);
return false;
}
//row_pointers is for pointing to image_data for reading the png with libpng
png_bytep *row_pointers = (png_bytep *) malloc(sizeof(png_bytep) * m_height);
if (!row_pointers) {
//clean up memory and close stuff
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
free(image_data);
fclose(fp);
return false;
}
// set the individual row_pointers to point at the correct offsets of image_data
for (int i = 0; i < m_height; ++i) {
row_pointers[m_height - 1 - i] = image_data + i * pot_rowbytes;
}
//read the png into image_data through row_pointers
png_read_image(png_ptr, row_pointers);
//Now generate the OpenGL texture object
glGenTextures(1, &m_texture_id);
glBindTexture(GL_TEXTURE_2D, m_texture_id);
glTexImage2D(GL_TEXTURE_2D,
0,
GL_RGBA,
pot_width,
pot_height,
0,
GL_RGBA,
GL_UNSIGNED_BYTE,
(GLvoid*) image_data);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
// TODO: make selectable via switch!
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
//clean up memory and close stuff
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
free(image_data);
free(row_pointers);
fclose(fp);
m_valid = true;
return true;
}
}

View file

@ -0,0 +1,65 @@
#pragma once
#include "glclasses.hpp"
#include <glm/vec2.hpp>
// based on sources of knoc/chaqu
namespace endofthejedi {
/**
* @brief This sprite struct stores all information needed to render an
* arbitrary PNG texture to a quad.
*
* If the loaded texture dimensions have no powers of a bit more space is
* allocated and extra padding is added.
*/
class ImageTexture {
public:
ImageTexture(const std::string &filename) : m_path(filename), m_valid(false)
{
}
~ImageTexture()
{
}
/**
* @brief Try to load a PNG image from file into an opengl texture.
*
* @param path Path of PNG file
* @param texture The used texture id will be saved there.
* @param width Width of the loaded texture in pixels.
* @param height Height of the loaded texture in pixels.
* @param uv_scale_x Horizontal portion of the screen which is padded to get
* power-of-two texture.
* @param uv_scale_y Vertical portion of the screen which is padded to get
* power-of-two texture.
*
* Note: The current active texture unit should be bound (GL_TEXTURE0 etc...)
* before calling this
*
* @return true if loading suceeded, false on errors.
*/
bool loadPng();
bool valid() const { return m_valid; }
glm::vec2 size() const { return glm::vec2(m_width, m_height); }
glm::vec2 uvScale() const { return glm::vec2(m_uv_scale_x, m_uv_scale_y); }
GLuint textureId() const { return m_texture_id; }
public:
std::string m_path; // path for the loaded texture is saved here
int m_width; // used width of the pixels of the texture
int m_height; // used height of the pixels of the texture
float m_uv_scale_x; // factor to scale uv-coordinates to get rid of non-power-of-two padding
float m_uv_scale_y; // factor to scale uv-coordinates to get rid of non-power-of-two padding
bool m_valid;
GLuint m_texture_id; // texture binding id
};
}

View file

@ -33,6 +33,16 @@ namespace endofthejedi {
addModel("../data/mesh/rocket.stl", &m_missileModel);
addModel("../data/mesh/planet_128.stl", &m_planetModel);
addModel("../data/mesh/ship_ufo.stl", &m_shipModel);
m_texture = new ImageTexture("../data/image/planet_mars.png");
std::cout<<"texture loading: " << m_texture->valid() << std::endl;
if (!m_texture->valid()) {
exit(-1);
}
glm::vec2 s = m_texture->size();
std::cout<<"texture size is " << s.x << " X " << s.y << std::endl;
exit(0);
}
void RendererPolygon3d::render(const game::State *state)

View file

@ -23,6 +23,7 @@
#include "particle_batch.hpp"
#include "polygon_model.hpp"
#include "image_texture.hpp"
namespace endofthejedi {
@ -87,5 +88,7 @@ namespace endofthejedi {
// TODO: put representation specialized for rendering in here
std::list<const game::Missile*> m_missiles;
std::list<const game::Ship*> m_ships;
ImageTexture *m_texture;
};
}

View file

@ -121,6 +121,7 @@ namespace sound {
int numActiveSounds(void)
{
return 0;
}
void deleteSound(SoundHandle *handle)