mirror of
https://github.com/ssloy/tinyraycaster.git
synced 2025-08-31 17:41:56 +02:00
load textures
This commit is contained in:
BIN
doc/009.png
Normal file
BIN
doc/009.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 7.3 KiB |
BIN
monsters.png
Normal file
BIN
monsters.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 7.4 KiB |
7462
stb_image.h
Normal file
7462
stb_image.h
Normal file
File diff suppressed because it is too large
Load Diff
@@ -2,11 +2,11 @@
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <vector>
|
||||
#include <cstdint>
|
||||
#include <cassert>
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#include "stb_image.h"
|
||||
|
||||
uint32_t pack_color(const uint8_t r, const uint8_t g, const uint8_t b, const uint8_t a=255) {
|
||||
return (a<<24) + (b<<16) + (g<<8) + r;
|
||||
@@ -43,6 +43,43 @@ void draw_rectangle(std::vector<uint32_t> &img, const size_t img_w, const size_t
|
||||
}
|
||||
}
|
||||
|
||||
bool load_texture(const std::string filename, std::vector<uint32_t> &texture, size_t &text_size, size_t &text_cnt) {
|
||||
int nchannels = -1, w, h;
|
||||
unsigned char *pixmap = stbi_load(filename.c_str(), &w, &h, &nchannels, 0);
|
||||
if (!pixmap) {
|
||||
std::cerr << "Error: can not load the textures" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (4!=nchannels) {
|
||||
std::cerr << "Error: the texture must be a 32 bit image" << std::endl;
|
||||
stbi_image_free(pixmap);
|
||||
return false;
|
||||
}
|
||||
|
||||
text_cnt = w/h;
|
||||
text_size = w/text_cnt;
|
||||
if (w!=h*int(text_cnt)) {
|
||||
std::cerr << "Error: the texture file must contain N square textures packed horizontally" << std::endl;
|
||||
stbi_image_free(pixmap);
|
||||
return false;
|
||||
}
|
||||
|
||||
texture = std::vector<uint32_t>(w*h);
|
||||
for (int j=0; j<h; j++) {
|
||||
for (int i=0; i<w; i++) {
|
||||
uint8_t r = pixmap[(i+j*w)*4+0];
|
||||
uint8_t g = pixmap[(i+j*w)*4+1];
|
||||
uint8_t b = pixmap[(i+j*w)*4+2];
|
||||
uint8_t a = pixmap[(i+j*w)*4+3];
|
||||
texture[i+j*w] = pack_color(r, g, b, a);
|
||||
}
|
||||
}
|
||||
stbi_image_free(pixmap);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int main() {
|
||||
const size_t win_w = 1024; // image width
|
||||
const size_t win_h = 512; // image height
|
||||
@@ -78,48 +115,56 @@ int main() {
|
||||
colors[i] = pack_color(rand()%255, rand()%255, rand()%255);
|
||||
}
|
||||
|
||||
std::vector<uint32_t> walltext; // textures for the walls
|
||||
size_t walltext_size; // texture dimensions (it is a square)
|
||||
size_t walltext_cnt; // number of different textures in the image
|
||||
if (!load_texture("../walltext.png", walltext, walltext_size, walltext_cnt)) {
|
||||
std::cerr << "Failed to load wall textures" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
const size_t rect_w = win_w/(map_w*2);
|
||||
const size_t rect_h = win_h/map_h;
|
||||
for (size_t frame=0; frame<360; frame++) {
|
||||
std::stringstream ss;
|
||||
ss << std::setfill('0') << std::setw(5) << frame << ".ppm";
|
||||
player_a += 2*M_PI/360;
|
||||
|
||||
framebuffer = std::vector<uint32_t>(win_w*win_h, pack_color(255, 255, 255)); // clear the screen
|
||||
|
||||
for (size_t j=0; j<map_h; j++) { // draw the map
|
||||
for (size_t i=0; i<map_w; i++) {
|
||||
if (map[i+j*map_w]==' ') continue; // skip empty spaces
|
||||
size_t rect_x = i*rect_w;
|
||||
size_t rect_y = j*rect_h;
|
||||
size_t icolor = map[i+j*map_w] - '0';
|
||||
assert(icolor<ncolors);
|
||||
draw_rectangle(framebuffer, win_w, win_h, rect_x, rect_y, rect_w, rect_h, colors[icolor]);
|
||||
}
|
||||
for (size_t j=0; j<map_h; j++) { // draw the map
|
||||
for (size_t i=0; i<map_w; i++) {
|
||||
if (map[i+j*map_w]==' ') continue; // skip empty spaces
|
||||
size_t rect_x = i*rect_w;
|
||||
size_t rect_y = j*rect_h;
|
||||
size_t icolor = map[i+j*map_w] - '0';
|
||||
assert(icolor<ncolors);
|
||||
draw_rectangle(framebuffer, win_w, win_h, rect_x, rect_y, rect_w, rect_h, colors[icolor]);
|
||||
}
|
||||
|
||||
for (size_t i=0; i<win_w/2; i++) { // draw the visibility cone AND the "3D" view
|
||||
float angle = player_a-fov/2 + fov*i/float(win_w/2);
|
||||
for (float t=0; t<20; t+=.01) {
|
||||
float cx = player_x + t*cos(angle);
|
||||
float cy = player_y + t*sin(angle);
|
||||
|
||||
size_t pix_x = cx*rect_w;
|
||||
size_t pix_y = cy*rect_h;
|
||||
framebuffer[pix_x + pix_y*win_w] = pack_color(160, 160, 160); // this draws the visibility cone
|
||||
|
||||
if (map[int(cx)+int(cy)*map_w]!=' ') { // our ray touches a wall, so draw the vertical column to create an illusion of 3D
|
||||
size_t icolor = map[int(cx)+int(cy)*map_w] - '0';
|
||||
assert(icolor<ncolors);
|
||||
size_t column_height = win_h/(t*cos(angle-player_a));
|
||||
draw_rectangle(framebuffer, win_w, win_h, win_w/2+i, win_h/2-column_height/2, 1, column_height, colors[icolor]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
drop_ppm_image(ss.str(), framebuffer, win_w, win_h);
|
||||
}
|
||||
|
||||
for (size_t i=0; i<win_w/2; i++) { // draw the visibility cone AND the "3D" view
|
||||
float angle = player_a-fov/2 + fov*i/float(win_w/2);
|
||||
for (float t=0; t<20; t+=.01) {
|
||||
float cx = player_x + t*cos(angle);
|
||||
float cy = player_y + t*sin(angle);
|
||||
|
||||
size_t pix_x = cx*rect_w;
|
||||
size_t pix_y = cy*rect_h;
|
||||
framebuffer[pix_x + pix_y*win_w] = pack_color(160, 160, 160); // this draws the visibility cone
|
||||
|
||||
if (map[int(cx)+int(cy)*map_w]!=' ') { // our ray touches a wall, so draw the vertical column to create an illusion of 3D
|
||||
size_t icolor = map[int(cx)+int(cy)*map_w] - '0';
|
||||
assert(icolor<ncolors);
|
||||
size_t column_height = win_h/(t*cos(angle-player_a));
|
||||
draw_rectangle(framebuffer, win_w, win_h, win_w/2+i, win_h/2-column_height/2, 1, column_height, colors[icolor]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const size_t texid = 4; // draw the 4th texture on the screen
|
||||
for (size_t i=0; i<walltext_size; i++) {
|
||||
for (size_t j=0; j<walltext_size; j++) {
|
||||
framebuffer[i+j*win_w] = walltext[i + texid*walltext_size + j*walltext_size*walltext_cnt];
|
||||
}
|
||||
}
|
||||
|
||||
drop_ppm_image("./out.ppm", framebuffer, win_w, win_h);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
BIN
walltext.png
Normal file
BIN
walltext.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 23 KiB |
Reference in New Issue
Block a user