Compare commits

...

10 Commits

17 changed files with 250 additions and 114 deletions

2
.gitignore vendored
View File

@ -2,4 +2,4 @@ bin/
lib/
.DS_Store
.idea/
cmake-build-*

View File

@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.2)
project(glTest)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -O1 -g -Wall")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -O0 -g -Wall")
set(CMAKE_BUILD_TYPE DEBUG)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/")

View File

@ -1,8 +1,47 @@
#version 330 core
smooth in vec3 theColor;
uniform mat4 mWorld;
uniform mat4 mView;
uniform mat4 mProjection;
uniform vec3 vEye;
in float zPos;
in vec3 norm;
out vec4 frag_colour;
void main () {
frag_colour = vec4(theColor, 1.0);
vec3 hsv_to_rgb(float h, float s, float v)
{
float c = v * s;
h = mod((h * 6.0), 6.0);
float x = c * (1.0 - abs(mod(h, 2.0) - 1.0));
vec3 color;
if (0.0 <= h && h < 1.0) {
color = vec3(c, x, 0.0);
} else if (1.0 <= h && h < 2.0) {
color = vec3(x, c, 0.0);
} else if (2.0 <= h && h < 3.0) {
color = vec3(0.0, c, x);
} else if (3.0 <= h && h < 4.0) {
color = vec3(0.0, x, c);
} else if (4.0 <= h && h < 5.0) {
color = vec3(x, 0.0, c);
} else if (5.0 <= h && h < 6.0) {
color = vec3(c, 0.0, x);
} else {
color = vec3(0.0, 0.0, 0.0);
}
color.rgb += v - c;
return color;
}
void main () {
vec3 materialColor = hsv_to_rgb(zPos, 1, 1);
float diffuse = clamp(dot(normalize(norm), -normalize(vec3(0,0,1))), 0.2, 0.6);
vec3 color = materialColor*diffuse;
frag_colour = vec4(color, 1.0);
}

View File

@ -3,41 +3,16 @@
uniform mat4 mWorld;
uniform mat4 mView;
uniform mat4 mProjection;
uniform vec3 vEye;
layout (location = 0) in vec3 vp;
layout (location = 1) in vec3 normals;
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 normal;
smooth out vec3 theColor;
vec3 hsv_to_rgb(float h, float s, float v)
{
float c = v * s;
h = mod((h * 6.0), 6.0);
float x = c * (1.0 - abs(mod(h, 2.0) - 1.0));
vec3 color;
if (0.0 <= h && h < 1.0) {
color = vec3(c, x, 0.0);
} else if (1.0 <= h && h < 2.0) {
color = vec3(x, c, 0.0);
} else if (2.0 <= h && h < 3.0) {
color = vec3(0.0, c, x);
} else if (3.0 <= h && h < 4.0) {
color = vec3(0.0, x, c);
} else if (4.0 <= h && h < 5.0) {
color = vec3(x, 0.0, c);
} else if (5.0 <= h && h < 6.0) {
color = vec3(c, 0.0, x);
} else {
color = vec3(0.0, 0.0, 0.0);
}
color.rgb += v - c;
return color;
}
out float zPos;
out vec3 norm;
void main () {
gl_Position = mProjection*mView*mWorld*vec4(vp, 1.0);
theColor = hsv_to_rgb(vp.z, 1, 1); //vec3(1.0, 1.0, 1.0);
norm = vec3(mProjection*mView*mWorld*vec4(normal, 0));
zPos = position.z;
gl_Position = mProjection*mView*mWorld*vec4(position, 1.0);
}

View File

@ -18,6 +18,8 @@ void Camera::init() {
glUniformMatrix4fv(view, 1, GL_FALSE, glm::value_ptr(_view));
GLint projection = glGetUniformLocation(*sp, "mProjection");
glUniformMatrix4fv(projection, 1, GL_FALSE, glm::value_ptr(_projection));
GLint eye = glGetUniformLocation(*sp, "vEye");
glUniform3fv(eye, 1, glm::value_ptr(_eye));
}
Camera *Camera::instance() {
@ -30,6 +32,8 @@ void Camera::updateView() {
ShaderProgram* sp = OGL::instance()->getCurShaderProgram();
GLint view = glGetUniformLocation(*sp, "mView");
glUniformMatrix4fv(view, 1, GL_FALSE, glm::value_ptr(_view));
GLint eye = glGetUniformLocation(*sp, "vEye");
glUniform3fv(eye, 1, glm::value_ptr(_eye));
}
void Camera::turnLeft(float angle) {

View File

@ -1,4 +1,5 @@
#include "GLObject.h"
#include "../utils.h"
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
@ -13,12 +14,8 @@ GLObject::~GLObject() {
}
void GLObject::create() {
std::size_t iCount = 0, vCount = 0;
std::unique_ptr<Vertex[]> vArray;
std::unique_ptr<GLuint[]> iArray;
std::tie(vArray, vCount) = generateVertices();
std::tie(iArray, iCount) = generateIndices();
generateVertices();
generateIndices();
GLuint vbo[2];
glGenBuffers(2, vbo);
@ -26,19 +23,24 @@ void GLObject::create() {
_indexVbo = vbo[1];
glBindBuffer(GL_ARRAY_BUFFER, _vertexVbo);
glBufferData(GL_ARRAY_BUFFER, vCount, vArray.get(), GL_STREAM_DRAW);
glBufferData(GL_ARRAY_BUFFER, _vertexCount*sizeof(Vertex), nullptr, GL_STREAM_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexVbo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, iCount, iArray.get(), GL_STREAM_DRAW);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, _indexCount*sizeof(GLuint), _indices.get(), GL_STREAM_DRAW);
_trianglesCount = iCount/sizeof(GLuint);
_trianglesCount = _indexCount*sizeof(GLuint)/sizeof(GLuint);
glGenVertexArrays(1, &_vao);
glBindVertexArray(_vao);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, _vertexVbo);
// configuring attributes of vertex
// coordinates
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), nullptr);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(0);
// normals
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6*sizeof(float), (GLchar*)(3*sizeof(float)));
glEnableVertexAttribArray(1);
}
void GLObject::rotate(glm::vec3 angles) {
@ -70,10 +72,8 @@ void GLObject::draw() {
}
void GLObject::update() {
std::size_t vCount = 0;
std::unique_ptr<Vertex[]> vArray;
std::tie(vArray, vCount) = generateVertices();
updateVertices();
glBindBuffer(GL_ARRAY_BUFFER, _vertexVbo);
// glBufferData(GL_ARRAY_BUFFER, _size*_size*sizeof(Vertex), NULL, GL_STREAM_DRAW);
glBufferData(GL_ARRAY_BUFFER, vCount, vArray.get(), GL_STREAM_DRAW);
//glBufferData(GL_ARRAY_BUFFER, _vertexCount*sizeof(Vertex), _vertices.get(), GL_STATIC_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, 0, _vertexCount*sizeof(Vertex), _vertices.get());
}

View File

@ -9,12 +9,6 @@
#include <memory>
#include <GL/glew.h>
template <typename T>
using ArrayWithSize = std::tuple<std::unique_ptr<T[]>,std::size_t>;
using VertexArray = ArrayWithSize<Vertex>;
using IndexArray = ArrayWithSize<GLuint>;
class GLObject: public IGLObject {
private:
GLuint _vertexVbo;
@ -24,6 +18,12 @@ private:
ShaderProgram* _sp;
GLuint _trianglesCount;
protected:
std::unique_ptr<Vertex[]> _vertices;
std::unique_ptr<GLuint[]> _indices;
std::size_t _vertexCount;
std::size_t _indexCount;
public:
GLObject(ShaderProgram *shaderProgram);
virtual ~GLObject();
@ -36,8 +36,9 @@ public:
void update() override final;
protected:
virtual VertexArray generateVertices() const = 0;
virtual IndexArray generateIndices() const = 0;
virtual void generateVertices() const = 0;
virtual void updateVertices() const = 0;
virtual void generateIndices() const = 0;
};

View File

@ -1,52 +1,116 @@
#include "Mesh.h"
#include <glm/gtc/type_ptr.hpp>
#include <glm/vec3.hpp>
#include <iostream>
Mesh::Mesh(ShaderProgram* shader, std::size_t size) : GLObject(shader), _size(size) {
Mesh::Mesh(ShaderProgram* shader, std::size_t size) : GLObject(shader),
_size(size),
_xs(size),
_ys(size),
_normals(2*(size-1)*(size-1)) {
_vertexCount = _size*_size;
_indexCount = (_size - 1)*(_size - 1)*6;
_vertices = std::make_unique<Vertex[]>(_vertexCount);
_indices = std::make_unique<GLuint[]>(_indexCount);
}
Mesh::~Mesh() {
}
VertexArray Mesh::generateVertices() const {
std::size_t u = _size, v = _size;
auto retVal = std::make_unique<Vertex[]>(u*v);
const float step = (exp(4) - 1)/_size;
for (std::size_t i = 0; i < u; i++)
for (std::size_t j = 0; j < v; j++)
{
// Vertex vertex;
float x = /*(float)i/(float)u*/ logf(i*step + 1)/4.0f - 0.5f;
float y = (float)j/(float)v - 0.5f;
retVal[j*u+i].coords[0] = x*3;
retVal[j*u+i].coords[1] = y*3;
retVal[j*u+i].coords[2] = heightMapFunc(j, i, x, y);
retVal[j*u+i].normal[0] = 1.0f;
retVal[j*u+i].normal[1] = 1.0f;
retVal[j*u+i].normal[2] = 1.0f;
void Mesh::generateVertices() const {
for(std::size_t j = 0; j < _size; ++j) {
for (std::size_t i = 0; i < _size; ++i) {
size_t idx = j*_size + i;
_vertices[idx].x = (float)i/_size - 0.5f;
_vertices[idx].y = (float)j/_size - 0.5f;
_vertices[idx].z = 0.f;
_vertices[idx].nx = 0.f;
_vertices[idx].ny = 0.f;
_vertices[idx].nz = 0.f;
}
}
return std::make_tuple(std::move(retVal), u*v*sizeof(Vertex));
}
IndexArray Mesh::generateIndices() const {
unsigned u = _size, v = _size;
auto indices = std::make_unique<GLuint[]>((u-1)*(v-1)*6);
inline ptrdiff_t Mesh::normalIndex(ptrdiff_t x, ptrdiff_t y) const {
return 2*(x + y*(_size - 1));
}
void Mesh::updateVertices() const {
for(std::size_t j = 0; j < _size; ++j) {
for(std::size_t i = 0; i < _size; ++i) {
std::size_t idx = j*_size + i;
_vertices[idx].z = heightMap(i, j);
}
}
// 1. Calc normals for all triangles
_normals.clear();
for(std::size_t j = 0; j < _size - 1; ++j) {
for(std::size_t i = 0; i < _size - 1; ++i) {
float x = _xs[i], x2 = _xs[i + 1];
float y = _ys[j], y2 = _ys[j + 1];
glm::vec3 p1(x, y, _vertices[j*_size + i + 1].z);
glm::vec3 p2(x2, y, _vertices[j*_size + i + 2].z);
glm::vec3 p3(x, y2, _vertices[(j + 1)*_size + i + 1].z);
glm::vec3 p4(x2, y2, _vertices[(j + 1)*_size + i + 2].z);
glm::vec3 v1 = p3 - p1;
glm::vec3 v2 = p4 - p1;
glm::vec3 v3 = p2 - p1;
glm::vec3 norm1 = glm::cross(v2, v1);
glm::vec3 norm2 = glm::cross(v3, v2);
_normals.emplace_back(norm1);
_normals.emplace_back(norm2);
}
}
// 2. Calc normals for all vertices based on precalculated normals for triangles
// Normal of vertex is an average of normals of adjacent triangles
size_t normalsCount = 2*(_size - 1)*(_size - 1);
for(std::size_t j = 0; j < _size; ++j) {
for (std::size_t i = 0; i < _size; ++i) {
glm::vec3 normal;
ptrdiff_t idx1 = normalIndex(i - 1, j - 1);
for(ptrdiff_t k = idx1; k < idx1 + 3; ++k) {
if(k >= 0 && k < normalsCount) {
normal += _normals[k];
}
}
ptrdiff_t idx2 = normalIndex(i - 1, j);
for(ptrdiff_t k = idx2; k < idx2 + 3; ++k) {
if(k >= 0 && k < normalsCount) {
normal += _normals[k];
}
}
size_t idx = j*_size + i;
_vertices[idx].nx = normal.x;
_vertices[idx].ny = normal.y;
_vertices[idx].nz = normal.z;
}
}
}
void Mesh::generateIndices() const {
GLuint u = (GLuint)_size, v = (GLuint)_size;
for (unsigned i = 0; i < (u - 1); i++)
for (unsigned j = 0; j < (v - 1); j++)
{
unsigned int indexa=j*(u-1)+i;
unsigned int indexb=j*u+i;
indices[indexa*6+0]=indexb;
indices[indexa*6+1]=indexb+1+u;
indices[indexa*6+2]=indexb+1;
GLuint indexa = j*(u - 1) + i;
GLuint indexb = j*u + i;
indices[indexa*6+3]=indexb;
indices[indexa*6+4]=indexb+u;
indices[indexa*6+5]=indexb+u+1;
_indices[indexa*6 + 0] = indexb;
_indices[indexa*6 + 1] = indexb + 1 + u;
_indices[indexa*6 + 2] = indexb + 1;
_indices[indexa*6 + 3] = indexb;
_indices[indexa*6 + 4] = indexb + u;
_indices[indexa*6 + 5] = indexb + u + 1;
}
return std::make_tuple(std::move(indices), (u-1)*(v-1)*6*sizeof(GLuint));
}

View File

@ -8,22 +8,31 @@
#include <cstddef>
#include <GL/glew.h>
#include <glm/glm.hpp>
#include <vector>
#include <array>
class Mesh: public GLObject {
protected:
std::size_t _size;
size_t _size;
std::vector<float> _xs;
std::vector<float> _ys;
mutable std::vector<glm::vec3> _normals;
public:
Mesh(ShaderProgram* shader, std::size_t size);
virtual ~Mesh();
protected:
VertexArray generateVertices() const override final;
IndexArray generateIndices() const override final;
private:
ptrdiff_t normalIndex(ptrdiff_t x, ptrdiff_t y) const;
protected:
virtual float heightMapFunc(std::size_t nx, std::size_t ny, float fx, float fy) const = 0;
void generateVertices() const override final;
void updateVertices() const override final;
void generateIndices() const override final;
protected:
virtual float heightMap(std::size_t nx, std::size_t ny) const = 0;
};

View File

@ -6,6 +6,13 @@ SpectralMesh::SpectralMesh(ShaderProgram *shader, std::size_t size): Mesh(shader
_data = new float[size*size];
_spectrLine = new float[2*size];
_spectrLineComplex = (fftwf_complex*)fftwf_malloc((_size + 1)*sizeof(fftwf_complex));
float step = 1.0f/size;
for(std::size_t i = 0; i < size; ++i) {
_xs[i] = log10f(step*i + 1) - 0.5f;
_ys[i] = step*i - 0.5f;
std::cout << "[" << _xs[i] << ", " << _ys[i] << "]" << std::endl;
}
}
SpectralMesh::~SpectralMesh() {
@ -14,8 +21,8 @@ SpectralMesh::~SpectralMesh() {
fftwf_free(_spectrLineComplex);
}
float SpectralMesh::heightMapFunc(std::size_t nx, std::size_t ny, float fx, float fy) const {
return *(_data + _size*nx + ny);
float SpectralMesh::heightMap(std::size_t nx, std::size_t ny) const {
return *(_data + _size*ny + nx);
}
void SpectralMesh::addLine(float *line, std::size_t depth) {

View File

@ -16,7 +16,7 @@ public:
void addLine(float* line, std::size_t depth = 0);
private:
float heightMapFunc(std::size_t nx, std::size_t ny, float fx, float fy) const override final;
float heightMap(std::size_t nx, std::size_t ny) const override final;
void normalizeArray(float* array, std::size_t size);
};

View File

@ -1,8 +1,10 @@
#include "WaveMesh.h"
float WaveMesh::heightMapFunc(std::size_t nx, std::size_t ny, float fx, float fy) const {
double d = 50*sqrt(fx*fx + fy*fy);
return static_cast<float>(cos(d - _shift)*exp(-d/10.0f)/2);
float WaveMesh::heightMap(std::size_t nx, std::size_t ny) const {
float x = _xs[nx];
float y = _xs[ny];
float d = 50*sqrtf(x*x + y*y);
return cosf(d - _shift)*expf(-d/10.0f)/4;
}
void WaveMesh::setShift(float shift) {
@ -11,7 +13,11 @@ void WaveMesh::setShift(float shift) {
}
WaveMesh::WaveMesh(ShaderProgram *shader, std::size_t size): Mesh(shader, size), _shift(0) {
float step = 1.0f/size;
for(std::size_t i = 0; i < size; ++i) {
_xs[i] = step*i - 0.5f;
_ys[i] = _xs[i];
}
}
WaveMesh::~WaveMesh() {

View File

@ -2,6 +2,7 @@
#define GLTEST_WAVEMESH_H
#include "Mesh.h"
#include <vector>
class WaveMesh: public Mesh {
private:
@ -13,7 +14,7 @@ public:
void setShift(float shift);
private:
float heightMapFunc(std::size_t nx, std::size_t ny, float fx, float fy) const override final;
float heightMap(std::size_t nx, std::size_t ny) const override final;
};

View File

@ -2,8 +2,17 @@
#define GLTEST_VERTEX_H
struct Vertex {
float coords[3];
float normal[3];
// coordinates
float x;
float y;
float z;
// normals
float nx;
float ny;
float nz;
};
#endif //GLTEST_VERTEX_H

View File

@ -1,6 +1,7 @@
#include "OGL.h"
#include "Camera.h"
#include "utils.h"
#include "GLObjects/WaveMesh.h"
#include <iostream>
#include <stdexcept>
@ -55,6 +56,10 @@ void cursorPositionCallback(GLFWwindow* window, double xpos, double ypos) {
static const float coeff = 0.01f;
if(glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS) {
Camera::instance()->mouseMoveAroundCenter(coeff*dx, coeff*dy);
// for(IGLObject* obj: OGL::instance()->_glObjects) {
// obj->rotate(glm::vec3(coeff*dy, 0.f, coeff*dx));
// obj->update();
// }
}
}
@ -70,6 +75,9 @@ void scrollCallback(GLFWwindow* window, double xoffset, double yoffset) {
}
}
void glfwErr(int code, const char* description) {
std::cout << "GLFW error - code: " << code << ", description: " << description << std::endl;
}
OGL::OGL() {
@ -102,13 +110,17 @@ void OGL::updateFpsCounter() const {
}
void OGL::init() {
glfwInit();
std::cout << glfwGetVersionString() << std::endl;
if(glfwInit() == GLFW_FALSE) {
throw new std::runtime_error("GLFW initialization error");
}
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
glfwWindowHint (GLFW_SAMPLES, 4);
glfwSetErrorCallback(glfwErr);
_window = glfwCreateWindow(1024, 1024, "OpenGL", nullptr, nullptr); // Windowed
glfwMakeContextCurrent(_window);
@ -138,7 +150,13 @@ void OGL::run() {
updateFpsCounter();
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// double time = glfwGetTime();
// float shift = (float)fmod(time, 2*3.1415926);
for(IGLObject* obj: _glObjects) {
// WaveMesh* mesh = dynamic_cast<WaveMesh*>(obj);
// mesh->setShift(shift*2);
//obj->scale(glm::vec3(1.0f, 1.0f, 1.0f));
obj->update();
obj->draw();

View File

@ -19,6 +19,7 @@ private:
OGL(const OGL &) = delete;
void operator=(const OGL &) = delete;
void updateFpsCounter() const;
friend void cursorPositionCallback(GLFWwindow* window, double xpos, double ypos);
public:
static OGL * instance();

View File

@ -1,8 +1,9 @@
#include "Shaders/ShaderProgram.h"
#include "Audio/AudioPlayer.h"
#include "GLObjects/SpectralMesh.h"
#include "GLObjects/WaveMesh.h"
#include "OGL.h"
#include "Camera.h"
#include "GLObjects/SpectralMesh.h"
#include <iostream>
@ -20,6 +21,7 @@ int main(int argc, char** argv) {
OGL::instance()->setCurShaderProgram(&program);
SpectralMesh mesh(&program, 512);
// WaveMesh mesh(&program, 128);
mesh.create();
OGL::instance()->addObject(&mesh);
@ -46,7 +48,7 @@ int main(int argc, char** argv) {
player.play();
OGL::instance()->run();
delete[] line;
// delete[] line;
} catch (std::exception& ex) {
std::cout << "exception: " << ex.what() << std::endl;
}