basic shader sort-of working (sip)

This commit is contained in:
Seiji Emery 2015-08-04 12:53:23 -07:00
parent 4e3cfd7c49
commit 9caf440746
3 changed files with 287 additions and 97 deletions

View file

@ -1,6 +1,8 @@
set(TARGET_NAME gpu-test)
AUTOSCRIBE_SHADER_LIB(gpu)
# This is not a testcase -- just set it up as a regular hifi project
setup_hifi_project(Quick Gui OpenGL)
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "Tests/manual-tests/")

View file

@ -0,0 +1,48 @@
//
// gputest_shaders.h
// hifi
//
// Created by Seiji Emery on 8/3/15.
//
//
#ifndef hifi_gputest_shaders_h
#define hifi_gputest_shaders_h
const std::string & basicVertexShader () {
static std::string src = R"(
// attribute vec3 position;
// attribute vec3 normal;
varying vec3 normal;
void main (void) {
// gl_Position = gl_ModelViewProjectionMatrix * vec4(position.xyz, 1.0);
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
normal = gl_Normal;
}
)";
return src;
}
const std::string & basicFragmentShader () {
static std::string src = R"(
#version 400
varying vec3 normal;
void main(void) {
gl_FragColor.rgb = vec3(0.7, 0.2, 0.5) + gl_FragCoord.xyz * 0.2;
vec3 diffuse = vec3(0.7, 0.2, 0.5);
vec3 light_normal = vec3(0.5, -0.5, 0.7);
gl_FragColor.rgb = diffuse * dot(light_normal, normal);
}
)";
return src;
}
#endif

View file

@ -38,13 +38,12 @@
#include <QTime>
#include <QTimer>
#include <QWindow>
#include <cstdio>
#include <PathUtils.h>
#include "gputest_shaders.h"
class RateCounter {
std::vector<float> times;
QElapsedTimer timer;
@ -81,15 +80,6 @@ public:
}
};
const char * basicVS =
" varying vec3 pos; "
" void main(void) { "
" gl_Position.xyz = pos; "
" } ";
const char * basicFS =
" void main(void) { "
" gl_FragColor.xyz = vec3(0.7, 0.2, 0.5); "
" } ";
const QString& getQmlDir() {
static QString dir;
@ -102,6 +92,170 @@ const QString& getQmlDir() {
return dir;
}
#define MOVE_PARAM(name) decltype(name) && name
struct BasicModel {
gpu::PipelinePointer pipeline;
// gpu::BufferPointer vertexBuffer;
// gpu::BufferPointer indexBuffer;
// gpu::BufferPointer normalBuffer;
gpu::BufferView vertices;
gpu::BufferView normals;
gpu::BufferPointer indices;
gpu::Stream::FormatPointer format;
BasicModel (MOVE_PARAM(pipeline), MOVE_PARAM(vertices), MOVE_PARAM(normals), MOVE_PARAM(indices), MOVE_PARAM(format))
: pipeline(pipeline), vertices(vertices), normals(normals), indices(indices), format(format) {}
// BasicModel (gpu::PipelinePointer && pipeline, gpu::BufferPointer && buffer, gpu::Stream::FormatPointer && format)
// : pipeline(pipeline), buffer(buffer), format(format) {}
};
typedef std::shared_ptr<BasicModel> BasicModelPointer;
#undef MOVE_PARAM
BasicModelPointer makeCube () {
// Axis-aligned cube, facing the user at +z
// coords == binary mapping of each index, with z inverted (front face faces camera,
// instead of away from the camera)
//
// -x,+y,-z ----------- +x,+y,-z
// ___--- | ___--- |
// -x,+y,+z --------- +x,+y,+z |
// | | | |
// | | | |
// | | | |
// | | | |
// | -x,-y,-z ------|---- +x,-y,-z
// | ___--- | ___----
// -x,-y,+z --------- +x,-y,+z
//
float s = 1.0f;
const glm::vec3 raw_verts[8] = {
// x, y, z
{ -s, -s, +s }, // 0b000 0x0
{ +s, -s, +s }, // 0b001 0x1
{ -s, +s, +s }, // 0b010 0x2
{ +s, +s, +s }, // 0b011 0x3
{ -s, -s, -s }, // 0b100 0x4
{ +s, -s, -s }, // 0b101 0x5
{ -s, +s, -s }, // 0b110 0x6
{ +s, +s, -s } // 0b111 0x7
};
const glm::vec3 raw_normals[6] = {
{ 0.0f, 0.0f, +1.0f }, // x > 0: 1, 3, 5, 7 (N 0)
{ 0.0f, 0.0f, -1.0f }, // x < 0: 0, 2, 4, 6 (N 1)
{ 0.0f, +1.0f, 0.0f }, // y > 0: 2, 3, 6, 7 (N 2)
{ 0.0f, -1.0f, 0.0f }, // y < 0: 0, 1, 4, 5 (N 3)
{ +1.0f, 0.0f, 0.0f }, // z > 0: 0, 1, 2, 3 (N 4)
{ -1.0f, 0.0f, 0.0f } // z < 0: 4, 5, 6, 7 (N 5)
};
const glm::vec3 cube_verts[24] = {
raw_verts[1], raw_verts[3], raw_verts[5], raw_verts[7],
raw_verts[0], raw_verts[2], raw_verts[4], raw_verts[6],
raw_verts[2], raw_verts[3], raw_verts[6], raw_verts[7],
raw_verts[0], raw_verts[1], raw_verts[4], raw_verts[5],
raw_verts[0], raw_verts[1], raw_verts[2], raw_verts[3],
raw_verts[4], raw_verts[5], raw_verts[6], raw_verts[7]
};
const glm::vec3 cube_normals[24] = {
raw_normals[0], raw_normals[0], raw_normals[0], raw_normals[0],
raw_normals[1], raw_normals[1], raw_normals[1], raw_normals[1],
raw_normals[2], raw_normals[2], raw_normals[2], raw_normals[2],
raw_normals[3], raw_normals[3], raw_normals[3], raw_normals[3],
raw_normals[4], raw_normals[4], raw_normals[4], raw_normals[4],
raw_normals[5], raw_normals[5], raw_normals[5], raw_normals[5]
};
int16_t cube_indices_tris[36];
for (int i = 0, k = 0; i < 36; k += 4) {
cube_indices_tris[i++] = k + 0;
cube_indices_tris[i++] = k + 3;
cube_indices_tris[i++] = k + 1;
cube_indices_tris[i++] = k + 0;
cube_indices_tris[i++] = k + 2;
cube_indices_tris[i++] = k + 3;
}
// const int16_t cube_indices_tris[36] {
// 0, 3, 1, 0, 2, 3,
// };
// const glm::vec3 cube_normals[] = {
// { 0.0f, 0.0f, 1.0f },
// { 0.0f, 0.0f, 1.0f },
// { 0.0f, 0.0f, 1.0f },
// { 0.0f, 0.0f, 1.0f },
// { -1.0f, 0.0f, 0.0f },
// { -1.0f, 0.0f, 0.0f },
// { -1.0f, 0.0f, 0.0f },
// { -1.0f, 0.0f, 0.0f },
// };
// const int16_t cube_indices[] = {
// 3, 1, 0, 2, 3, 0,
// 6, 2, 0, 4, 6, 0,
// };
gpu::Stream::FormatPointer format = std::make_shared<gpu::Stream::Format>();
format->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, gpu::Element::VEC3F_XYZ);
format->setAttribute(gpu::Stream::NORMAL, gpu::Stream::NORMAL, gpu::Element::VEC3F_XYZ);
auto vertexBuffer = std::make_shared<gpu::Buffer>(24 * sizeof(glm::vec3), (gpu::Byte*)cube_verts);
auto normalBuffer = std::make_shared<gpu::Buffer>(24 * sizeof(glm::vec3), (gpu::Byte*)cube_normals);
gpu::BufferPointer indexBuffer = std::make_shared<gpu::Buffer>(36 * sizeof(int16_t), (gpu::Byte*)cube_indices_tris);
auto positionElement = format->getAttributes().at(gpu::Stream::POSITION)._element;
auto normalElement = format->getAttributes().at(gpu::Stream::NORMAL)._element;
gpu::BufferView vertexView { vertexBuffer, positionElement };
gpu::BufferView normalView { normalBuffer, normalElement };
// Create shaders
auto vs = gpu::ShaderPointer(gpu::Shader::createVertex(basicVertexShader()));
auto fs = gpu::ShaderPointer(gpu::Shader::createPixel(basicFragmentShader()));
auto shader = gpu::ShaderPointer(gpu::Shader::createProgram(vs, fs));
gpu::Shader::BindingSet bindings;
if (!gpu::Shader::makeProgram(*shader, bindings)) {
printf("Could not compile shader\n");
if (!vs)
printf("bad vertex shader\n");
if (!fs)
printf("bad fragment shader\n");
if (!shader)
printf("bad shader program\n");
exit(-1);
}
auto state = std::make_shared<gpu::State>();
// state->setAntialiasedLineEnable(true);
state->setMultisampleEnable(true);
state->setDepthTest({ true });
auto pipeline = gpu::PipelinePointer(gpu::Pipeline::create(shader, state));
return std::make_shared<BasicModel>(
std::move(pipeline),
std::move(vertexView),
std::move(normalView),
std::move(indexBuffer),
std::move(format)
);
}
void renderCube(gpu::Batch & batch, const BasicModel & cube) {
batch.setPipeline(cube.pipeline);
batch.setInputFormat(cube.format);
batch.setInputBuffer(gpu::Stream::POSITION, cube.vertices);
batch.setInputBuffer(gpu::Stream::NORMAL, cube.normals);
batch.setIndexBuffer(gpu::INT16, cube.indices, 0);
// batch.drawIndexed(gpu::TRIANGLES, 12);
batch.draw(gpu::TRIANGLES, 24);
}
// Create a simple OpenGL window that renders text in various ways
class QTestWindow : public QWindow {
Q_OBJECT
@ -111,9 +265,7 @@ class QTestWindow : public QWindow {
gpu::ContextPointer _context;
gpu::PipelinePointer _pipeline;
gpu::BufferPointer _buffer;
gpu::Stream::FormatPointer _format;
BasicModelPointer _cubeModel;
//TextRenderer* _textRenderer[4];
RateCounter fps;
@ -154,63 +306,10 @@ public:
batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLORS, { 1.0, 0.0, 0.5, 1.0 });
_context->render(batch);
// Create default shaders
_cubeModel = makeCube();
std::string vsSource (basicVS);
std::string fsSource (basicFS);
auto vs = gpu::ShaderPointer(gpu::Shader::createVertex(vsSource));
auto fs = gpu::ShaderPointer(gpu::Shader::createPixel(fsSource));
auto shader = gpu::ShaderPointer(gpu::Shader::createProgram(vs, fs));
gpu::Shader::BindingSet bindings;
if (!gpu::Shader::makeProgram(*shader, bindings)) {
printf("Could not compile shader");
exit(-1);
}
// auto shader = gpu::StandardShaderLib::getDrawViewportQuadTransformTexcoordVS();
auto state = std::make_shared<gpu::State>();
_pipeline = gpu::PipelinePointer(gpu::Pipeline::create(shader, state));
float z = 10.0f;
const glm::vec3 vertices[] = {
{ -1.0f, 1.0f, z },
{ 1.0f, -1.0f, z },
{ -1.0f, -1.0f, z }
};
_buffer = std::make_shared<gpu::Buffer>(sizeof(vertices), (const gpu::Byte*)vertices);
_format = std::make_shared<gpu::Stream::Format>();
_format->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ));
// {
// QOpenGLDebugLogger* logger = new QOpenGLDebugLogger(this);
// logger->initialize(); // initializes in the current context, i.e. ctx
// logger->enableMessages();
// connect(logger, &QOpenGLDebugLogger::messageLogged, this, [&](const QOpenGLDebugMessage & debugMessage) {
// qDebug() << debugMessage;
// });
// // logger->startLogging(QOpenGLDebugLogger::SynchronousLogging);
// }
// qDebug() << (const char*)glGetString(GL_VERSION);
//_textRenderer[0] = TextRenderer::getInstance(SANS_FONT_FAMILY, 12, false);
//_textRenderer[1] = TextRenderer::getInstance(SERIF_FONT_FAMILY, 12, false,
// TextRenderer::SHADOW_EFFECT);
//_textRenderer[2] = TextRenderer::getInstance(MONO_FONT_FAMILY, 48, -1,
// false, TextRenderer::OUTLINE_EFFECT);
//_textRenderer[3] = TextRenderer::getInstance(INCONSOLATA_FONT_FAMILY, 24);
// glEnable(GL_BLEND);
// glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// glClearColor(0.2f, 0.2f, 0.2f, 1);
// glDisable(GL_DEPTH_TEST);
makeCurrent();
_context->syncCache();
// makeCurrent();
// _context->syncCache();
setFramePosition(QPoint(-1000, 0));
resize(QSize(800, 600));
@ -257,41 +356,81 @@ void QTestWindow::draw() {
gpu::Batch batch;
static int frameNum = 0;
frameNum++;
batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLORS, { 1.0, float(frameNum % 60)/60.0f, 0.5, 1.0 });
// _context->render(batch);
float t = frameNum / 120.0f;
float k = (frameNum % 120) / 120;
float ks = glm::sin(glm::pi<float>() * 2.0f * k);
batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLORS, { 0.1, 0.1, 0.1, 1.0 });
// batch.clearDepthFramebuffer(-10000.0f);
// batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLORS, { 1.0, float(frameNum % 60)/60.0f, 0.5, 1.0 });
batch.setViewportTransform({ 0, 0, _size.width() * devicePixelRatio(), _size.height() * devicePixelRatio() });
//// batch.clear();
// batch.setViewportTransform({ 0, 0, _size.width() * devicePixelRatio(), _size.height() * devicePixelRatio() });
//
glm::quat cubeOrientation;
//
batch.setViewTransform(Transform());
batch.setProjectionTransform(glm::mat4());
// batch.setProjectionTransform(_viewFrustrum->getProjection());
batch.setModelTransform(Transform().setRotation(cubeOrientation));
batch.setPipeline(_pipeline);
batch.setInputBuffer(gpu::Stream::POSITION, _buffer, 0, 3);
batch.setInputFormat(_format);
batch.draw(gpu::TRIANGLES, 3);
// camera at x: 5 * sin(t)
// y: 1,
// z: +10
// obj at (0, 0, 0)
// camera is looking at obj (using glm::lookAt)
glm::vec3 up { 0.0f, 1.0f, 0.0f };
glm::vec3 unitscale { 1.0f };
float cube_angle = 0.0f;
// glm::vec3 cube_pos {
// 0.0f,
// 0.0f,
// 0.0f
// };
glm::vec3 cube_pos {
20.0f * cos(t * 5.0f),
10.0f * sin(t * 2.5f) + 1.0f,
-15.0f + float(int(t * int(1e3)) % int(1e4)) / 1e3
};
// float cube_angle = 360.0f * k * 1.25 + 120.0f * k * 0.1f;
// glm::quat cube_rotation = glm::angleAxis(glm::radians(cube_angle), up);
glm::quat cube_rotation;
Transform cube_transform { cube_rotation, unitscale, cube_pos };
// glm::vec3 cam_pos { 0.0f, 0.0f, -10.0f };
glm::vec3 cam_pos { 5.0f * sin(t * 0.1f), 1.0f, -10.0f };
glm::quat cam_rotation = glm::quat_cast(glm::lookAt(cam_pos, cube_pos, up));
cam_rotation.w = -cam_rotation.w;
Transform cam_transform { cam_rotation, unitscale, cam_pos };
float fov_degrees = 120.0f;
// float aspect_ratio = _size.height() / (_size.width() || 1.0f);
float aspect_ratio = 16.0f / 9.0f;
float near_clip = 0.1f;
float far_clip = 1000.0f;
auto projection = glm::perspective(glm::radians(fov_degrees), aspect_ratio, near_clip, far_clip);
batch.setProjectionTransform(projection);
batch.setViewTransform(cam_transform);
batch.setModelTransform(cube_transform);
batch.setModelTransform(Transform().setTranslation({ 20.0f * cos(t * 5.0f), 10.0f * sin(t * 2.5f + 1.0f), -15.0f + float(int(t * 1000) % 10000) / 1e3f}));
// batch.setPipeline(_pipeline);
// batch.setInputBuffer(gpu::Stream::POSITION, _buffer, 0, 3);
// batch.setInputFormat(_format);
// batch.draw(gpu::TRIANGLES, 3);
renderCube(batch, *_cubeModel);
_context->render(batch);
//
//// gpu::Stream::Format format;
//// format.setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, gpu::Element(gpu::Vec3, gpu::FLOAT, gpu::XYZ));
//// batch.setInputBuffer(gpu::Stream::POSITION, _trianglePosBuffer, )
//
//
//// glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//// glViewport(0, 0, _size.width() * devicePixelRatio(), _size.height() * devicePixelRatio());
//
//// _context->swapBuffers(this);
//// glFinish();
//
_qGlContext->swapBuffers(this);
// glFinish();
fps.increment();
if (fps.elapsed() >= 2.0f) {
qDebug() << "FPS: " << fps.rate(); // This prints out the frames per 2 secs (ie. half of the actual fps) bug...?
qDebug() << "FPS: " << fps.rate() * 2.0f; // This prints out the frames per 2 secs (ie. half of the actual fps) bug...?
fps.reset();
}
}
@ -300,7 +439,8 @@ int main(int argc, char** argv) {
QGuiApplication app(argc, argv);
QTestWindow window;
QTimer timer;
timer.setInterval(1000 / 120.0f);
// timer.setInterval(1000 / 120.0f);
timer.setInterval(0);
app.connect(&timer, &QTimer::timeout, &app, [&] {
window.draw();
});