Audio module, simple text rendering
This commit is contained in:
parent
e96fd909ea
commit
1770acbfef
@ -2,6 +2,7 @@
|
||||
|
||||
#include "graphics/Texture.h"
|
||||
#include "graphics/Shader.h"
|
||||
#include "graphics/Font.h"
|
||||
|
||||
Assets::~Assets() {
|
||||
for (auto& iter : shaders){
|
||||
@ -11,6 +12,10 @@ Assets::~Assets() {
|
||||
for (auto& iter : textures){
|
||||
delete iter.second;
|
||||
}
|
||||
|
||||
for (auto& iter : fonts){
|
||||
delete iter.second;
|
||||
}
|
||||
}
|
||||
|
||||
Texture* Assets::getTexture(std::string name){
|
||||
@ -29,3 +34,12 @@ Shader* Assets::getShader(std::string name){
|
||||
void Assets::store(Shader* shader, std::string name){
|
||||
shaders[name] = shader;
|
||||
}
|
||||
|
||||
|
||||
Font* Assets::getFont(std::string name){
|
||||
return fonts[name];
|
||||
}
|
||||
|
||||
void Assets::store(Font* font, std::string name){
|
||||
fonts[name] = font;
|
||||
}
|
||||
|
||||
@ -6,10 +6,12 @@
|
||||
|
||||
class Texture;
|
||||
class Shader;
|
||||
class Font;
|
||||
|
||||
class Assets {
|
||||
std::unordered_map<std::string, Texture*> textures;
|
||||
std::unordered_map<std::string, Shader*> shaders;
|
||||
std::unordered_map<std::string, Font*> fonts;
|
||||
public:
|
||||
~Assets();
|
||||
Texture* getTexture(std::string name);
|
||||
@ -17,6 +19,9 @@ public:
|
||||
|
||||
Shader* getShader(std::string name);
|
||||
void store(Shader* shader, std::string name);
|
||||
|
||||
Font* getFont(std::string name);
|
||||
void store(Font* font, std::string name);
|
||||
};
|
||||
|
||||
#endif /* SRC_ASSETS_H_ */
|
||||
|
||||
180
src/audio/Audio.cpp
Normal file
180
src/audio/Audio.cpp
Normal file
@ -0,0 +1,180 @@
|
||||
#include "Audio.h"
|
||||
#include "audioutil.h"
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
#include <AL/al.h>
|
||||
#include <AL/alc.h>
|
||||
|
||||
ALCdevice* Audio::device;
|
||||
ALCcontext* Audio::context;
|
||||
unsigned Audio::maxSources;
|
||||
unsigned Audio::maxBuffers = 1024;
|
||||
std::vector<ALSource*> Audio::allsources;
|
||||
std::vector<ALSource*> Audio::freesources;
|
||||
std::vector<ALBuffer*> Audio::allbuffers;
|
||||
std::vector<ALBuffer*> Audio::freebuffers;
|
||||
|
||||
bool ALSource::setBuffer(ALBuffer* buffer){
|
||||
alSourcei(id, AL_BUFFER, buffer->id);
|
||||
return alCheck();
|
||||
}
|
||||
|
||||
bool ALSource::play(){
|
||||
alSourcePlay(id);
|
||||
return alCheck();
|
||||
}
|
||||
|
||||
bool ALSource::setPosition(glm::vec3 position){
|
||||
alSource3f(id, AL_POSITION, position.x, position.y, position.z);
|
||||
return alCheck();
|
||||
}
|
||||
|
||||
bool ALSource::setVelocity(glm::vec3 velocity){
|
||||
alSource3f(id, AL_VELOCITY, velocity.x, velocity.y, velocity.z);
|
||||
return alCheck();
|
||||
}
|
||||
|
||||
bool ALSource::setLoop(bool loop){
|
||||
alSourcei(id, AL_LOOPING, AL_TRUE ? loop : AL_FALSE);
|
||||
return alCheck();
|
||||
}
|
||||
|
||||
bool ALSource::setGain(float gain) {
|
||||
alSourcef(id, AL_GAIN, gain);
|
||||
return alCheck();
|
||||
}
|
||||
|
||||
|
||||
bool ALSource::setPitch(float pitch) {
|
||||
alSourcef(id, AL_PITCH, pitch);
|
||||
return alCheck();
|
||||
}
|
||||
|
||||
bool ALBuffer::load(int format, const char* data, int size, int freq){
|
||||
alBufferData(id, format, data, size, freq);
|
||||
return alCheck();
|
||||
}
|
||||
|
||||
|
||||
bool Audio::initialize(){
|
||||
device = alcOpenDevice(nullptr);
|
||||
if (device == nullptr)
|
||||
return false;
|
||||
context = alcCreateContext(device, nullptr);
|
||||
if (!alcMakeContextCurrent(context)){
|
||||
alcCloseDevice(device);
|
||||
return false;
|
||||
}
|
||||
if (!alCheck())
|
||||
return false;
|
||||
|
||||
ALCint size;
|
||||
alcGetIntegerv(device, ALC_ATTRIBUTES_SIZE, 1, &size);
|
||||
std::vector<ALCint> attrs(size);
|
||||
alcGetIntegerv(device, ALC_ALL_ATTRIBUTES, size, &attrs[0]);
|
||||
for(size_t i=0; i<attrs.size(); ++i){
|
||||
if (attrs[i] == ALC_MONO_SOURCES){
|
||||
std::cout << "max mono sources: " << attrs[i+1] << std::endl;
|
||||
maxSources = attrs[i+1];
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Audio::finalize(){
|
||||
for (ALSource* source : allsources){
|
||||
alSourceStop(source->id); alCheck();
|
||||
alDeleteSources(1, &source->id); alCheck();
|
||||
}
|
||||
|
||||
for (ALBuffer* buffer : allbuffers){
|
||||
alDeleteBuffers(1, &buffer->id); alCheck();
|
||||
}
|
||||
|
||||
alcMakeContextCurrent(context);
|
||||
alcDestroyContext(context);
|
||||
if (!alcCloseDevice(device)){
|
||||
std::cerr << "device not closed!" << std::endl;
|
||||
}
|
||||
device = nullptr;
|
||||
context = nullptr;
|
||||
}
|
||||
|
||||
ALSource* Audio::getFreeSource(){
|
||||
if (!freesources.empty()){
|
||||
ALSource* source = freesources.back();
|
||||
freesources.pop_back();
|
||||
return source;
|
||||
}
|
||||
if (allsources.size() == maxSources){
|
||||
std::cerr << "attempted to create new source, but limit is " << maxSources << std::endl;
|
||||
return nullptr;
|
||||
}
|
||||
ALuint id;
|
||||
alGenSources(1, &id);
|
||||
if (!alCheck())
|
||||
return nullptr;
|
||||
|
||||
ALSource* source = new ALSource(id);
|
||||
allsources.push_back(source);
|
||||
return source;
|
||||
}
|
||||
|
||||
ALBuffer* Audio::getFreeBuffer(){
|
||||
if (!freebuffers.empty()){
|
||||
ALBuffer* buffer = freebuffers.back();
|
||||
freebuffers.pop_back();
|
||||
return buffer;
|
||||
}
|
||||
if (allbuffers.size() == maxBuffers){
|
||||
std::cerr << "attempted to create new ALbuffer, but limit is " << maxBuffers << std::endl;
|
||||
return nullptr;
|
||||
}
|
||||
ALuint id;
|
||||
alGenBuffers(1, &id);
|
||||
if (!alCheck())
|
||||
return nullptr;
|
||||
|
||||
ALBuffer* buffer = new ALBuffer(id);
|
||||
allbuffers.push_back(buffer);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void Audio::freeSource(ALSource* source){
|
||||
freesources.push_back(source);
|
||||
}
|
||||
|
||||
void Audio::freeBuffer(ALBuffer* buffer){
|
||||
freebuffers.push_back(buffer);
|
||||
}
|
||||
|
||||
bool Audio::get_available_devices(std::vector<std::string>& devicesVec){
|
||||
const ALCchar* devices;
|
||||
devices = alcGetString(device, ALC_DEVICE_SPECIFIER);
|
||||
if (!alCheck())
|
||||
return false;
|
||||
|
||||
const char* ptr = devices;
|
||||
|
||||
devicesVec.clear();
|
||||
|
||||
do {
|
||||
devicesVec.push_back(std::string(ptr));
|
||||
ptr += devicesVec.back().size() + 1;
|
||||
}
|
||||
while(*(ptr + 1) != '\0');
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Audio::setOrientation(glm::vec3 position, glm::vec3 velocity, glm::vec3 at, glm::vec3 up){
|
||||
ALfloat listenerOri[] = { at.x, at.y, at.z, up.x, up.y, up.z };
|
||||
|
||||
alListener3f(AL_POSITION, position.x, position.y, position.z);
|
||||
alCheck();
|
||||
alListener3f(AL_VELOCITY, velocity.x, velocity.y, velocity.z);
|
||||
alCheck();
|
||||
alListenerfv(AL_ORIENTATION, listenerOri);
|
||||
alCheck();
|
||||
}
|
||||
61
src/audio/Audio.h
Normal file
61
src/audio/Audio.h
Normal file
@ -0,0 +1,61 @@
|
||||
#ifndef SRC_AUDIO_AUDIO_H_
|
||||
#define SRC_AUDIO_AUDIO_H_
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include <AL/al.h>
|
||||
#include <AL/alc.h>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
|
||||
struct ALBuffer;
|
||||
|
||||
struct ALSource {
|
||||
ALuint id;
|
||||
ALSource(ALuint id) : id(id) {}
|
||||
|
||||
bool setPosition(glm::vec3 position);
|
||||
bool setVelocity(glm::vec3 velocity);
|
||||
bool setBuffer(ALBuffer* buffer);
|
||||
bool setLoop(bool loop);
|
||||
bool setGain(float gain);
|
||||
bool setPitch(float pitch);
|
||||
bool play();
|
||||
};
|
||||
|
||||
struct ALBuffer {
|
||||
ALuint id;
|
||||
ALBuffer(ALuint id) : id(id) {}
|
||||
bool load(int format, const char* data, int size, int freq);
|
||||
};
|
||||
|
||||
class Audio {
|
||||
static ALCdevice* device;
|
||||
static ALCcontext* context;
|
||||
|
||||
static std::vector<ALSource*> allsources;
|
||||
static std::vector<ALSource*> freesources;
|
||||
|
||||
static std::vector<ALBuffer*> allbuffers;
|
||||
static std::vector<ALBuffer*> freebuffers;
|
||||
|
||||
static unsigned maxSources;
|
||||
static unsigned maxBuffers;
|
||||
|
||||
public:
|
||||
static ALSource* getFreeSource();
|
||||
static ALBuffer* getFreeBuffer();
|
||||
static void freeSource(ALSource* source);
|
||||
static void freeBuffer(ALBuffer* buffer);
|
||||
|
||||
static bool initialize();
|
||||
static void finalize();
|
||||
static bool get_available_devices(std::vector<std::string>& devicesVec);
|
||||
|
||||
static void setOrientation(glm::vec3 position, glm::vec3 velocity, glm::vec3 at, glm::vec3 up);
|
||||
|
||||
};
|
||||
|
||||
#endif /* SRC_AUDIO_AUDIO_H_ */
|
||||
194
src/audio/audioutil.cpp
Normal file
194
src/audio/audioutil.cpp
Normal file
@ -0,0 +1,194 @@
|
||||
#include "audioutil.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <cstring>
|
||||
#include <type_traits>
|
||||
#include <AL/al.h>
|
||||
#include <AL/alc.h>
|
||||
|
||||
|
||||
bool is_big_endian(void){
|
||||
union {
|
||||
uint32_t i;
|
||||
char c[4];
|
||||
} bint = {0x01020304};
|
||||
|
||||
return bint.c[0] == 1;
|
||||
}
|
||||
|
||||
std::int32_t convert_to_int(char* buffer, std::size_t len){
|
||||
std::int32_t a = 0;
|
||||
if(!is_big_endian())
|
||||
std::memcpy(&a, buffer, len);
|
||||
else
|
||||
for(std::size_t i = 0; i < len; ++i)
|
||||
reinterpret_cast<char*>(&a)[3 - i] = buffer[i];
|
||||
return a;
|
||||
}
|
||||
|
||||
bool check_al_errors(const std::string& filename, const std::uint_fast32_t line){
|
||||
ALenum error = alGetError();
|
||||
if(error != AL_NO_ERROR){
|
||||
std::cerr << "OpenAL ERROR (" << filename << ": " << line << ")\n" ;
|
||||
switch(error){
|
||||
case AL_INVALID_NAME:
|
||||
std::cerr << "AL_INVALID_NAME: a bad name (ID) was passed to an OpenAL function";
|
||||
break;
|
||||
case AL_INVALID_ENUM:
|
||||
std::cerr << "AL_INVALID_ENUM: an invalid enum value was passed to an OpenAL function";
|
||||
break;
|
||||
case AL_INVALID_VALUE:
|
||||
std::cerr << "AL_INVALID_VALUE: an invalid value was passed to an OpenAL function";
|
||||
break;
|
||||
case AL_INVALID_OPERATION:
|
||||
std::cerr << "AL_INVALID_OPERATION: the requested operation is not valid";
|
||||
break;
|
||||
case AL_OUT_OF_MEMORY:
|
||||
std::cerr << "AL_OUT_OF_MEMORY: the requested operation resulted in OpenAL running out of memory";
|
||||
break;
|
||||
default:
|
||||
std::cerr << "UNKNOWN AL ERROR: " << error;
|
||||
}
|
||||
std::cerr << std::endl;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool load_wav_file_header(std::ifstream& file,
|
||||
std::uint8_t& channels,
|
||||
std::int32_t& sampleRate,
|
||||
std::uint8_t& bitsPerSample,
|
||||
ALsizei& size){
|
||||
char buffer[4];
|
||||
if(!file.is_open())
|
||||
return false;
|
||||
|
||||
// the RIFF
|
||||
if(!file.read(buffer, 4)){
|
||||
std::cerr << "ERROR: could not read RIFF" << std::endl;
|
||||
return false;
|
||||
}
|
||||
if(std::strncmp(buffer, "RIFF", 4) != 0){
|
||||
std::cerr << "ERROR: file is not a valid WAVE file (header doesn't begin with RIFF)" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// the size of the file
|
||||
if(!file.read(buffer, 4)){
|
||||
std::cerr << "ERROR: could not read size of file" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// the WAVE
|
||||
if(!file.read(buffer, 4)){
|
||||
std::cerr << "ERROR: could not read WAVE" << std::endl;
|
||||
return false;
|
||||
}
|
||||
if(std::strncmp(buffer, "WAVE", 4) != 0){
|
||||
std::cerr << "ERROR: file is not a valid WAVE file (header doesn't contain WAVE)" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// "fmt/0"
|
||||
if(!file.read(buffer, 4)){
|
||||
std::cerr << "ERROR: could not read fmt/0" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// this is always 16, the size of the fmt data chunk
|
||||
if(!file.read(buffer, 4)){
|
||||
std::cerr << "ERROR: could not read the 16" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// PCM should be 1?
|
||||
if(!file.read(buffer, 2)){
|
||||
std::cerr << "ERROR: could not read PCM" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// the number of channels
|
||||
if(!file.read(buffer, 2)){
|
||||
std::cerr << "ERROR: could not read number of channels" << std::endl;
|
||||
return false;
|
||||
}
|
||||
channels = convert_to_int(buffer, 2);
|
||||
|
||||
// sample rate
|
||||
if(!file.read(buffer, 4)){
|
||||
std::cerr << "ERROR: could not read sample rate" << std::endl;
|
||||
return false;
|
||||
}
|
||||
sampleRate = convert_to_int(buffer, 4);
|
||||
|
||||
// (sampleRate * bitsPerSample * channels) / 8
|
||||
if(!file.read(buffer, 4)){
|
||||
std::cerr << "ERROR: could not read (sampleRate * bitsPerSample * channels) / 8" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// ?? dafaq
|
||||
if(!file.read(buffer, 2)){
|
||||
std::cerr << "ERROR: could not read dafaq" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// bitsPerSample
|
||||
if(!file.read(buffer, 2)){
|
||||
std::cerr << "ERROR: could not read bits per sample" << std::endl;
|
||||
return false;
|
||||
}
|
||||
bitsPerSample = convert_to_int(buffer, 2);
|
||||
|
||||
// data chunk header "data"
|
||||
if(!file.read(buffer, 4)){
|
||||
std::cerr << "ERROR: could not read data chunk header" << std::endl;
|
||||
return false;
|
||||
}
|
||||
if(std::strncmp(buffer, "data", 4) != 0){
|
||||
std::cerr << "ERROR: file is not a valid WAVE file (doesn't have 'data' tag)" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// size of data
|
||||
if(!file.read(buffer, 4)){
|
||||
std::cerr << "ERROR: could not read data size" << std::endl;
|
||||
return false;
|
||||
}
|
||||
size = convert_to_int(buffer, 4);
|
||||
|
||||
/* cannot be at the end of file */
|
||||
if(file.eof()){
|
||||
std::cerr << "ERROR: reached EOF on the file" << std::endl;
|
||||
return false;
|
||||
}
|
||||
if(file.fail()){
|
||||
std::cerr << "ERROR: fail state set on the file" << std::endl;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
char* load_wav(const std::string& filename,
|
||||
std::uint8_t& channels,
|
||||
std::int32_t& sampleRate,
|
||||
std::uint8_t& bitsPerSample,
|
||||
ALsizei& size){
|
||||
std::ifstream in(filename, std::ios::binary);
|
||||
if(!in.is_open()){
|
||||
std::cerr << "ERROR: Could not open \"" << filename << "\"" << std::endl;
|
||||
return nullptr;
|
||||
}
|
||||
if(!load_wav_file_header(in, channels, sampleRate, bitsPerSample, size)){
|
||||
std::cerr << "ERROR: Could not load wav header of \"" << filename << "\"" << std::endl;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
char* data = new char[size];
|
||||
|
||||
in.read(data, size);
|
||||
|
||||
return data;
|
||||
}
|
||||
44
src/audio/audioutil.h
Normal file
44
src/audio/audioutil.h
Normal file
@ -0,0 +1,44 @@
|
||||
#ifndef SRC_AUDIO_AUDIOUTIL_H_
|
||||
#define SRC_AUDIO_AUDIOUTIL_H_
|
||||
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
#include <AL/al.h>
|
||||
|
||||
#define alCheck() check_al_errors(__FILE__, __LINE__)
|
||||
|
||||
bool check_al_errors(const std::string& filename, const std::uint_fast32_t line);
|
||||
|
||||
bool load_wav_file_header(std::ifstream& file,
|
||||
std::uint8_t& channels,
|
||||
std::int32_t& sampleRate,
|
||||
std::uint8_t& bitsPerSample,
|
||||
ALsizei& size);
|
||||
|
||||
char* load_wav(const std::string& filename,
|
||||
std::uint8_t& channels,
|
||||
std::int32_t& sampleRate,
|
||||
std::uint8_t& bitsPerSample,
|
||||
ALsizei& size);
|
||||
|
||||
static inline ALenum to_al_format(short channels, short samples){
|
||||
bool stereo = (channels > 1);
|
||||
|
||||
switch (samples) {
|
||||
case 16:
|
||||
if (stereo)
|
||||
return AL_FORMAT_STEREO16;
|
||||
else
|
||||
return AL_FORMAT_MONO16;
|
||||
case 8:
|
||||
if (stereo)
|
||||
return AL_FORMAT_STEREO8;
|
||||
else
|
||||
return AL_FORMAT_MONO8;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* SRC_AUDIO_AUDIOUTIL_H_ */
|
||||
@ -5,6 +5,7 @@
|
||||
#include "Assets.h"
|
||||
#include "graphics/Shader.h"
|
||||
#include "graphics/Texture.h"
|
||||
#include "graphics/Font.h"
|
||||
#include "window/Window.h"
|
||||
|
||||
#include "voxels/Block.h"
|
||||
@ -32,6 +33,17 @@ bool _load_texture(Assets* assets, std::string filename, std::string name){
|
||||
return true;
|
||||
}
|
||||
|
||||
bool _load_font(Assets* assets, std::string filename, std::string name){
|
||||
Texture* texture = load_texture(filename);
|
||||
if (texture == nullptr){
|
||||
std::cerr << "failed to load bitmap font '" << name << "'" << std::endl;
|
||||
return false;
|
||||
}
|
||||
Font* font = new Font(texture);
|
||||
assets->store(font, name);
|
||||
return true;
|
||||
}
|
||||
|
||||
int initialize_assets(Assets* assets) {
|
||||
#define LOAD_SHADER(VERTEX, FRAGMENT, NAME) \
|
||||
if (!_load_shader(assets, VERTEX, FRAGMENT, NAME))\
|
||||
@ -39,12 +51,19 @@ int initialize_assets(Assets* assets) {
|
||||
#define LOAD_TEXTURE(FILENAME, NAME) \
|
||||
if (!_load_texture(assets, FILENAME, NAME))\
|
||||
return 1;
|
||||
#define LOAD_FONT(FILENAME, NAME) \
|
||||
if (!_load_font(assets, FILENAME, NAME))\
|
||||
return 1;
|
||||
|
||||
LOAD_SHADER("res/main.glslv", "res/main.glslf", "main");
|
||||
LOAD_SHADER("res/crosshair.glslv", "res/crosshair.glslf", "crosshair");
|
||||
LOAD_SHADER("res/lines.glslv", "res/lines.glslf", "lines");
|
||||
LOAD_SHADER("res/ui.glslv", "res/ui.glslf", "ui");
|
||||
|
||||
LOAD_TEXTURE("res/block.png", "block");
|
||||
//LOAD_TEXTURE("res/font.png", "font");
|
||||
|
||||
LOAD_FONT("res/font.png", "normal");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
#include "Batch2D.h"
|
||||
#include "Mesh.h"
|
||||
#include "Texture.h"
|
||||
|
||||
#include <GL/glew.h>
|
||||
|
||||
Batch2D::Batch2D(size_t capacity) : capacity(capacity),
|
||||
offset(0),
|
||||
@ -8,11 +11,80 @@ Batch2D::Batch2D(size_t capacity) : capacity(capacity),
|
||||
2, 2, 4, 0 //null terminator
|
||||
};
|
||||
|
||||
buffer = new float[capacity];
|
||||
mesh = new Mesh(nullptr, 0, attrs);
|
||||
buffer = new float[capacity * 8];
|
||||
mesh = new Mesh(buffer, 0, attrs);
|
||||
index = 0;
|
||||
|
||||
unsigned char pixels[] = {
|
||||
255, 255, 255, 255,
|
||||
};
|
||||
blank = new Texture(pixels, 1, 1);
|
||||
_texture = nullptr;
|
||||
}
|
||||
|
||||
Batch2D::~Batch2D(){
|
||||
delete blank;
|
||||
delete buffer;
|
||||
delete mesh;
|
||||
}
|
||||
|
||||
void Batch2D::begin(){
|
||||
_texture = nullptr;
|
||||
blank->bind();
|
||||
}
|
||||
|
||||
void Batch2D::vertex(float x, float y,
|
||||
float u, float v,
|
||||
float r, float g, float b, float a) {
|
||||
buffer[index++] = x;
|
||||
buffer[index++] = y;
|
||||
buffer[index++] = u;
|
||||
buffer[index++] = v;
|
||||
buffer[index++] = r;
|
||||
buffer[index++] = g;
|
||||
buffer[index++] = b;
|
||||
buffer[index++] = a;
|
||||
}
|
||||
|
||||
void Batch2D::texture(Texture* new_texture){
|
||||
if (_texture == new_texture)
|
||||
return;
|
||||
_texture = new_texture;
|
||||
if (new_texture == nullptr)
|
||||
blank->bind();
|
||||
else
|
||||
new_texture->bind();
|
||||
}
|
||||
|
||||
void Batch2D::rect(float x, float y, float w, float h){
|
||||
const float r = color.r;
|
||||
const float g = color.g;
|
||||
const float b = color.b;
|
||||
const float a = color.a;
|
||||
|
||||
vertex(x, y, 0, 0, r,g,b,a);
|
||||
vertex(x+w, y+h, 1, 1, r,g,b,a);
|
||||
vertex(x, y+h, 0, 1, r,g,b,a);
|
||||
|
||||
vertex(x, y, 0, 0, r,g,b,a);
|
||||
vertex(x+w, y, 1, 0, r,g,b,a);
|
||||
vertex(x+w, y+h, 1, 1, r,g,b,a);
|
||||
}
|
||||
|
||||
void Batch2D::rect(float x, float y, float w, float h,
|
||||
float u, float v, float tx, float ty,
|
||||
float r, float g, float b, float a){
|
||||
vertex(x, y, u, v, r,g,b,a);
|
||||
vertex(x+w, y+h, u+tx, v+ty, r,g,b,a);
|
||||
vertex(x, y+h, u, v+ty, r,g,b,a);
|
||||
|
||||
vertex(x, y, u, v, r,g,b,a);
|
||||
vertex(x+w, y, u+tx, v, r,g,b,a);
|
||||
vertex(x+w, y+h, u+tx, v+ty, r,g,b,a);
|
||||
}
|
||||
|
||||
void Batch2D::render() {
|
||||
mesh->reload(buffer, index / 8);
|
||||
mesh->draw(GL_TRIANGLES);
|
||||
index = 0;
|
||||
}
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
class Mesh;
|
||||
class Texture;
|
||||
|
||||
class Batch2D {
|
||||
float* buffer;
|
||||
@ -12,6 +13,10 @@ class Batch2D {
|
||||
size_t offset;
|
||||
glm::vec4 color;
|
||||
Mesh* mesh;
|
||||
size_t index;
|
||||
|
||||
Texture* blank;
|
||||
Texture* _texture;
|
||||
|
||||
void vertex(float x, float y,
|
||||
float u, float v,
|
||||
@ -20,7 +25,12 @@ public:
|
||||
Batch2D(size_t capacity);
|
||||
~Batch2D();
|
||||
|
||||
void begin();
|
||||
void texture(Texture* texture);
|
||||
void rect(float x, float y, float w, float h);
|
||||
void rect(float x, float y, float w, float h,
|
||||
float u, float v, float tx, float ty,
|
||||
float r, float g, float b, float a);
|
||||
void render();
|
||||
};
|
||||
|
||||
|
||||
40
src/graphics/Font.cpp
Normal file
40
src/graphics/Font.cpp
Normal file
@ -0,0 +1,40 @@
|
||||
#include "Font.h"
|
||||
#include "Texture.h"
|
||||
#include "Batch2D.h"
|
||||
|
||||
Font::Font(Texture* texture) : texture(texture) {
|
||||
}
|
||||
|
||||
Font::~Font(){
|
||||
delete texture;
|
||||
}
|
||||
|
||||
|
||||
void Font::draw(Batch2D* batch, std::string text, int x, int y) {
|
||||
for (char c : text){
|
||||
float u = (c % 16) / 16.0f;
|
||||
float v = 1.0f - ((c / 16) / 16.0f) - 1.0f/16.0f;
|
||||
batch->rect(x, y, 8, 8, u, v, 1.0f/16.0f, 1.0f/16.0f, 1,1,1,1);
|
||||
|
||||
int gw = 7;
|
||||
switch (c){
|
||||
case 'l':
|
||||
case 'i':
|
||||
case 'j':
|
||||
case '|':
|
||||
case '.':
|
||||
case ',':
|
||||
case ':':
|
||||
case ';':
|
||||
gw = 3;
|
||||
break;
|
||||
case 't':
|
||||
gw = 5;
|
||||
break;
|
||||
case ' ':
|
||||
gw = 3;
|
||||
break;
|
||||
}
|
||||
x += gw;
|
||||
}
|
||||
}
|
||||
18
src/graphics/Font.h
Normal file
18
src/graphics/Font.h
Normal file
@ -0,0 +1,18 @@
|
||||
#ifndef GRAPHICS_FONT_H_
|
||||
#define GRAPHICS_FONT_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
class Texture;
|
||||
class Batch2D;
|
||||
|
||||
class Font {
|
||||
public:
|
||||
Texture* texture;
|
||||
Font(Texture* texture);
|
||||
~Font();
|
||||
|
||||
void draw(Batch2D* batch, std::string text, int x, int y);
|
||||
};
|
||||
|
||||
#endif /* GRAPHICS_FONT_H_ */
|
||||
@ -2,6 +2,7 @@
|
||||
// sudo apt install libgl-dev libglew-dev libglfw3-dev libpng-dev libglm-dev
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
#include <stdint.h>
|
||||
|
||||
#define GLEW_STATIC
|
||||
#include <GL/glew.h>
|
||||
@ -22,6 +23,7 @@ using namespace glm;
|
||||
#include "graphics/Mesh.h"
|
||||
#include "graphics/VoxelRenderer.h"
|
||||
#include "graphics/LineBatch.h"
|
||||
#include "graphics/Batch2D.h"
|
||||
#include "window/Window.h"
|
||||
#include "window/Events.h"
|
||||
#include "window/Camera.h"
|
||||
@ -40,6 +42,8 @@ using namespace glm;
|
||||
#include "physics/Hitbox.h"
|
||||
#include "physics/PhysicsSolver.h"
|
||||
|
||||
#include "audio/Audio.h"
|
||||
#include "audio/audioutil.h"
|
||||
#include "Assets.h"
|
||||
#include "objects/Player.h"
|
||||
|
||||
@ -86,6 +90,9 @@ void update_controls(PhysicsSolver* physics,
|
||||
Player* player,
|
||||
float delta){
|
||||
|
||||
if (Events::jpressed(GLFW_KEY_ESCAPE)){
|
||||
Window::setShouldClose(true);
|
||||
}
|
||||
if (Events::jpressed(GLFW_KEY_TAB)){
|
||||
Events::toogleCursor();
|
||||
}
|
||||
@ -244,16 +251,13 @@ void update_interaction(Chunks* chunks, PhysicsSolver* physics, Player* player,
|
||||
int WIDTH = 1280;
|
||||
int HEIGHT = 720;
|
||||
|
||||
#define GRAVITY 19.6f
|
||||
#define DEFAULT_PLAYER_SPEED 4.0f
|
||||
|
||||
vec3 spawnpoint(-320, 255, 32);
|
||||
|
||||
|
||||
int main() {
|
||||
setup_definitions();
|
||||
|
||||
Window::initialize(WIDTH, HEIGHT, "VoxelEngine Part-11");
|
||||
Audio::initialize();
|
||||
|
||||
Window::initialize(WIDTH, HEIGHT, "Window 2.0");
|
||||
Events::initialize();
|
||||
|
||||
std::cout << "-- loading assets" << std::endl;
|
||||
@ -266,12 +270,12 @@ int main() {
|
||||
}
|
||||
std::cout << "-- loading world" << std::endl;
|
||||
|
||||
Camera *camera = new Camera(spawnpoint, radians(90.0f));
|
||||
Camera *camera = new Camera(vec3(-320,255,32), radians(90.0f));
|
||||
WorldFiles *wfile = new WorldFiles("world/", REGION_VOL * (CHUNK_VOL * 2 + 8));
|
||||
Chunks *chunks = new Chunks(34,1,34, 0,0,0);
|
||||
|
||||
|
||||
Player* player = new Player(vec3(camera->position), DEFAULT_PLAYER_SPEED, camera);
|
||||
Player* player = new Player(vec3(camera->position), 4.0f, camera);
|
||||
wfile->readPlayer(player);
|
||||
camera->rotation = mat4(1.0f);
|
||||
camera->rotate(player->camY, player->camX, 0);
|
||||
@ -279,7 +283,7 @@ int main() {
|
||||
std::cout << "-- preparing systems" << std::endl;
|
||||
|
||||
VoxelRenderer renderer(1024*1024);
|
||||
PhysicsSolver physics(vec3(0,-GRAVITY,0));
|
||||
PhysicsSolver physics(vec3(0,-9.8f*2.0f,0));
|
||||
Lighting lighting(chunks);
|
||||
|
||||
init_renderer();
|
||||
@ -297,16 +301,13 @@ int main() {
|
||||
|
||||
std::cout << "-- initializing finished" << std::endl;
|
||||
|
||||
|
||||
while (!Window::isShouldClose()){
|
||||
frame++;
|
||||
float currentTime = glfwGetTime();
|
||||
delta = currentTime - lastTime;
|
||||
lastTime = currentTime;
|
||||
|
||||
if (Events::jpressed(GLFW_KEY_ESCAPE)){
|
||||
Window::setShouldClose(true);
|
||||
}
|
||||
|
||||
if (Events::jpressed(GLFW_KEY_O)){
|
||||
occlusion = !occlusion;
|
||||
}
|
||||
@ -336,8 +337,8 @@ int main() {
|
||||
|
||||
delete assets;
|
||||
finalize_renderer();
|
||||
Audio::finalize();
|
||||
Events::finalize();
|
||||
Window::terminate();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -37,7 +37,10 @@ void Camera::rotate(float x, float y, float z){
|
||||
|
||||
mat4 Camera::getProjection(){
|
||||
float aspect = (float)Window::width / (float)Window::height;
|
||||
return glm::perspective(fov*zoom, aspect, 0.05f, 1500.0f);
|
||||
if (perspective)
|
||||
return glm::perspective(fov*zoom, aspect, 0.05f, 1500.0f);
|
||||
else
|
||||
return glm::ortho(0.0f, fov*aspect, 0.0f, fov);
|
||||
}
|
||||
|
||||
mat4 Camera::getView(){
|
||||
|
||||
@ -23,6 +23,7 @@ public:
|
||||
float fov;
|
||||
float zoom;
|
||||
mat4 rotation;
|
||||
bool perspective = true;
|
||||
Camera(vec3 position, float fov);
|
||||
|
||||
void rotate(float x, float y, float z);
|
||||
|
||||
@ -37,17 +37,26 @@ int attrs[] = {
|
||||
2, 0 //null terminator
|
||||
};
|
||||
|
||||
int uiscale = 2;
|
||||
|
||||
LineBatch *lineBatch;
|
||||
Batch2D *batch;
|
||||
Camera *uicamera;
|
||||
|
||||
void init_renderer(){
|
||||
crosshair = new Mesh(vertices, 4, attrs);
|
||||
lineBatch = new LineBatch(4096);
|
||||
|
||||
batch = new Batch2D(1024);
|
||||
uicamera = new Camera(glm::vec3(), Window::height / uiscale);
|
||||
uicamera->perspective = false;
|
||||
}
|
||||
|
||||
|
||||
void finalize_renderer(){
|
||||
delete crosshair;
|
||||
delete lineBatch;
|
||||
delete batch;
|
||||
}
|
||||
|
||||
void draw_chunk(size_t index, Camera* camera, Shader* shader, bool occlusion){
|
||||
@ -100,6 +109,7 @@ void draw_world(Camera* camera, Assets* assets,
|
||||
Chunks* chunks, bool occlusion){
|
||||
glClearColor(0.7f,0.71f,0.73f,1);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
_chunks = chunks;
|
||||
|
||||
@ -151,6 +161,19 @@ void draw_world(Camera* camera, Assets* assets,
|
||||
lineBatch->line(camera->position.x, camera->position.y-0.5f, camera->position.z, camera->position.x+0.1f, camera->position.y-0.5f, camera->position.z, 1, 0, 0, 1);
|
||||
lineBatch->line(camera->position.x, camera->position.y-0.5f, camera->position.z, camera->position.x, camera->position.y-0.5f, camera->position.z+0.1f, 0, 0, 1, 1);
|
||||
lineBatch->render();
|
||||
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
Shader* uishader = assets->getShader("ui");
|
||||
uishader->use();
|
||||
uishader->uniformMatrix("u_projview", uicamera->getProjection());
|
||||
|
||||
Font* font = assets->getFont("normal");
|
||||
batch->begin();
|
||||
batch->texture(font->texture);
|
||||
font->draw(batch, "void Font::draw(Batch2D* batch, std::string text, int x, int y) {", 10, 10);
|
||||
//batch->rect(0, 0, 256, 256);
|
||||
batch->render();
|
||||
}
|
||||
|
||||
#endif // WORLD_RENDERER_CPP
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user