Models now draw in a single draw call

This commit is contained in:
Grayson Riffe (Laptop) 2021-10-01 01:21:27 -05:00
parent 037ad47468
commit ba19742bfe
19 changed files with 257 additions and 168 deletions

View File

@ -4,7 +4,7 @@ void MainState::onEnter() {
Log("MainState onEnter!");
camera->setType(nf::Camera::Type::FIRST_PERSON);
ap.load("example.nfpack");
test.create(ap["normal.obj"]);
test.create(ap["2mats.obj"]);
test.setPosition(0.0, 0.05, -5.0);
plane.create(nf::BaseAssets::cube);
plane.setPosition(0.0, -1.0, 0.0);
@ -57,7 +57,7 @@ void MainState::update(double deltaTime) {
offset += 2.0 * deltaTime;
if (app->isKeyHeld(NFI_DOWN))
offset -= 2.0 * deltaTime;
test.setRotation(offset * 10.0, 0.0, 0.0);
test.setRotation(0.0, 0.0, -offset * 20.0);
light.setPosition(nf::Vec3(std::sin(circle) * 10.0, 5.0, std::cos(circle) * 10.0));
circle += 2.0 * deltaTime;
@ -77,8 +77,8 @@ void MainState::render(nf::Renderer& renderer) {
renderer.render(test);
renderer.render(plane);
renderer.render(light);
/*renderer.render(light2);
renderer.render(light3);*/
renderer.render(light2);
renderer.render(light3);
renderer.render(text);
renderer.render(uiTex);
renderer.render(button);

View File

@ -4,19 +4,16 @@ in vec3 fragPos;
in vec2 texCoord;
in vec3 normal;
in mat3 tbn;
flat in int matNum;
struct Material {
bool hasDiffuseTex;
sampler2D diffuseTexture;
vec3 diffuseColor;
bool hasSpecTex;
sampler2D specularTexture;
float specPower;
bool hasNormTex;
sampler2D normalTexture;
};
uniform Material material;
uniform bool hasDiffuseTex[32];
uniform sampler2D diffuseTexture[32];
uniform vec3 diffuseColor[32];
uniform bool hasSpecTex[32];
uniform sampler2D specularTexture[32];
uniform float specPower[32];
uniform bool hasNormTex[32];
uniform sampler2D normalTexture[32];
layout(location = 0) out vec3 pos;
layout(location = 1) out vec3 normals;
@ -25,25 +22,9 @@ layout(location = 3) out vec3 specular;
void main() {
pos = fragPos;
if (material.hasNormTex) {
normals = texture(material.normalTexture, texCoord).xyz;
normals = normals * 2.0 - 1.0;
normals = normalize(tbn * normals);
}
else
normals = normal;
if (material.hasDiffuseTex)
diffuse = texture(material.diffuseTexture, texCoord).rgb;
else
diffuse = material.diffuseColor;
specular.r = material.specPower;
if (material.hasSpecTex)
specular.g = texture(material.specularTexture, texCoord).r;
else
specular.g = 1.0;
normals = hasNormTex[matNum] ? normalize(tbn * (texture(normalTexture[matNum], texCoord).xyz * 2.0 - 1.0)) : normal;
diffuse = hasDiffuseTex[matNum] ? texture(diffuseTexture[matNum], texCoord).rgb : diffuseColor[matNum];
specular.r = specPower[matNum];
specular.g = hasSpecTex[matNum] ? texture(specularTexture[matNum], texCoord).r : 1.0;
specular.b = 1.0;
}

View File

@ -4,6 +4,7 @@ layout(location = 0) in vec3 pos;
layout(location = 1) in vec2 texCoords;
layout(location = 2) in vec3 normals;
layout(location = 3) in vec3 tangent;
layout(location = 4) in int matN;
uniform mat4 model;
uniform mat4 view;
@ -12,8 +13,8 @@ uniform mat4 proj;
out vec3 fragPos;
out vec2 texCoord;
out vec3 normal;
out vec3 tang;
out mat3 tbn;
flat out int matNum;
void main() {
vec4 world = model * vec4(pos, 1.0);
@ -25,6 +26,7 @@ void main() {
normal = n;
vec3 b = cross(n, t);
tbn = mat3(t, b, n);
matNum = matN;
gl_Position = proj * view * world;
}

View File

@ -0,0 +1,26 @@
# Blender MTL File: 'None'
# Material Count: 2
newmtl mat1
Ns 225.000000
Ka 1.000000 1.000000 1.000000
Kd 0.800000 0.800000 0.800000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.450000
d 1.000000
illum 2
map_Kd diff.png
map_Ks spec.png
newmtl mat2
Ns 225.000000
Ka 1.000000 1.000000 1.000000
Kd 0.800000 0.800000 0.800000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.450000
d 1.000000
illum 2
map_Bump brickwall_normal.jpg
map_Kd brickwall.jpg

View File

@ -0,0 +1,47 @@
# Blender v2.93.3 OBJ File: ''
# www.blender.org
mtllib 2mats.mtl
o Cube_Cube.001
v -1.000000 -1.000000 1.000000
v -1.000000 1.000000 1.000000
v -1.000000 -1.000000 -1.000000
v -1.000000 1.000000 -1.000000
v 1.000000 -1.000000 1.000000
v 1.000000 1.000000 1.000000
v 1.000000 -1.000000 -1.000000
v 1.000000 1.000000 -1.000000
vt -2.000000 0.000000
vt -1.000000 1.000000
vt -2.000000 1.000000
vt -1.000000 0.000000
vt 0.000000 1.000000
vt 1.000000 0.000000
vt 2.000000 1.000000
vt 1.000000 1.000000
vt 1.000000 2.000000
vt 0.000000 2.000000
vt 0.000000 -1.000000
vt 0.000000 0.000000
vt 2.000000 0.000000
vt 1.000000 -1.000000
vn -1.0000 0.0000 0.0000
vn 0.0000 0.0000 -1.0000
vn 0.0000 0.0000 1.0000
vn 0.0000 -1.0000 0.0000
vn 0.0000 1.0000 0.0000
vn 1.0000 0.0000 0.0000
usemtl mat1
s off
f 2/1/1 3/2/1 1/3/1
f 4/4/2 7/5/2 3/2/2
f 6/6/3 1/7/3 5/8/3
f 7/5/4 1/9/4 3/10/4
f 4/11/5 6/6/5 8/12/5
f 2/1/1 4/4/1 3/2/1
f 4/4/2 8/12/2 7/5/2
f 6/6/3 2/13/3 1/7/3
f 7/5/4 5/8/4 1/9/4
f 4/11/5 2/14/5 6/6/5
usemtl mat2
f 8/12/6 5/8/6 7/5/6
f 8/12/6 6/6/6 5/8/6

View File

@ -2,6 +2,7 @@
#include "Application.h"
#include "Model.h"
#include "Texture.h"
#include "Utility.h"
namespace nf {
@ -53,9 +54,15 @@ namespace nf {
m_nfObjects.clear();
for (Model* curr : m_modelsToDelete)
delete curr;
if (!curr->isBaseAsset())
delete curr;
m_modelsToDelete.clear();
for (Texture* curr : m_texturesToDelete)
if (!curr->isBaseAsset())
delete curr;
m_texturesToDelete.clear();
delete camera;
app = nullptr;
}

View File

@ -53,10 +53,10 @@ namespace nf {
};
m_vao = new VertexArray;
m_vao->addBuffer(nullptr, 0);
m_vao->push<float>(2);
m_vao->pushFloat(2);
m_vao->finishBufferLayout();
m_vao->addBuffer(tc, sizeof(tc));
m_vao->push<float>(2);
m_vao->pushFloat(2);
m_vao->finishBufferLayout();
if (!Application::getApp()->getCurrentState()->isRunning())

View File

@ -113,7 +113,7 @@ namespace nf {
};
m_vao = new VertexArray;
m_vao->addBuffer(vb, sizeof(vb));
m_vao->push<float>(3);
m_vao->pushFloat(3);
m_vao->finishBufferLayout();
if (!Application::getApp()->getCurrentState()->isRunning())

View File

@ -90,7 +90,7 @@ namespace nf {
}
void Entity::destroy() {
if (m_constructed && m_model && !m_model->isBaseAsset()) {
if (m_constructed && m_model) {
Application::getApp()->getCurrentState()->m_modelsToDelete.insert(m_model);
m_model = nullptr;
}

View File

@ -60,10 +60,10 @@ namespace nf {
}
m_vao = new VertexArray;
m_vao->addBuffer(nullptr, 0);
m_vao->push<float>(2);
m_vao->pushFloat(2);
m_vao->finishBufferLayout();
m_vao->addBuffer(nullptr, 0);
m_vao->push<float>(2);
m_vao->pushFloat(2);
m_vao->finishBufferLayout();
if (m_string == "NFLoadingText") {

View File

@ -43,10 +43,10 @@ namespace nf {
};
m_vao = new VertexArray;
m_vao->addBuffer(nullptr, 0);
m_vao->push<float>(2);
m_vao->pushFloat(2);
m_vao->finishBufferLayout();
m_vao->addBuffer(tc, sizeof(tc));
m_vao->push<float>(2);
m_vao->pushFloat(2);
m_vao->finishBufferLayout();
if (!Application::getApp()->getCurrentState()->isRunning())

View File

@ -1,96 +1,22 @@
#include "Model.h"
#include <map>
#include <algorithm>
#include "glm/glm.hpp"
#include "glm/gtc/matrix_transform.hpp"
#include "GL/glew.h"
#include "Application.h"
#include "Texture.h"
#include "Shader.h"
#include "Utility.h"
namespace nf {
Material::Material(const void* vb, const size_t vbSize, const void* tc, const size_t tcSize, const void* vn, const size_t vnSize, const void* tan, const size_t tanSize, const void* ib, const unsigned int ibCount, ATexture* diffTex, Vec3& diffColor, ATexture* specTex, float shininess, ATexture* normalTex) {
m_vao = new VertexArray();
m_vao->addBuffer(vb, vbSize);
m_vao->push<float>(3);
m_vao->finishBufferLayout();
m_vao->addBuffer(tc, tcSize);
m_vao->push<float>(2);
m_vao->finishBufferLayout();
m_vao->addBuffer(vn, vnSize);
m_vao->push<float>(3);
m_vao->finishBufferLayout();
m_vao->addBuffer(tan, tanSize);
m_vao->push<float>(3);
m_vao->finishBufferLayout();
m_ib = new IndexBuffer(ib, ibCount);
if (diffTex) {
m_hasDiffuse = true;
if (diffTex->alreadyLoaded)
m_diffuseTexture = diffTex->loadedTexture;
else
m_diffuseTexture = new Texture(diffTex);
}
m_diffColor = diffColor;
if (specTex) {
m_hasSpecular = true;
if (specTex->alreadyLoaded)
m_specularTexture = specTex->loadedTexture;
else
m_specularTexture = new Texture(specTex, true);
}
m_shininess = shininess;
if (normalTex) {
m_hasNormal = true;
if (normalTex->alreadyLoaded)
m_normalTexture = normalTex->loadedTexture;
else
m_normalTexture = new Texture(normalTex, true);
}
}
void Material::render(Shader* shader, bool onlyDepth) {
m_vao->bind();
m_ib->bind();
if (!onlyDepth) {
if (m_hasDiffuse) {
shader->setUniform("material.hasDiffuseTex", true);
m_diffuseTexture->bind();
}
else {
shader->setUniform("material.hasDiffuseTex", false);
glm::vec3 color(m_diffColor.x, m_diffColor.y, m_diffColor.z);
shader->setUniform("material.diffuseColor", color);
}
if (m_hasSpecular) {
shader->setUniform("material.hasSpecTex", true);
m_specularTexture->bind(1);
shader->setUniform("material.specularTexture", 1);
}
else
shader->setUniform("material.hasSpecTex", false);
if (m_hasNormal) {
shader->setUniform("material.hasNormTex", true);
m_normalTexture->bind(2);
shader->setUniform("material.normalTexture", 2);
}
else
shader->setUniform("material.hasNormTex", false);
shader->setUniform("material.specPower", m_shininess);
}
glDrawElements(GL_TRIANGLES, m_ib->getCount(), GL_UNSIGNED_INT, nullptr);
}
Material::~Material() {
delete m_diffuseTexture;
delete m_specularTexture;
delete m_normalTexture;
}
Model::Model(AModel* model) :
m_base(model->isBaseAsset)
{
if (model->neededTextures.size() > 32)
Error("Model exceedes 32 texture limit!");
std::string obj = model->data;
unsigned int startMtlPos = obj.find("newmtl");
if (startMtlPos == std::string::npos)
@ -293,6 +219,13 @@ namespace nf {
return std::memcmp((void*)this, (void*)&other, sizeof(Vertex)) > 0;
}
};
std::vector<float> vboPositions;
std::vector<float> vboTexCoords;
std::vector<float> vboNormals;
std::vector<float> vboTangents;
std::vector<int> vboMaterialIndices;
std::vector<unsigned int> vboIndices;
int matCount = 0;
for (auto& m : mats) {
std::string curr = m.first;
std::map<Vertex, unsigned int> vertexMap;
@ -325,23 +258,101 @@ namespace nf {
}
TempMaterial& curr2 = *m.second;
ATexture* diff = nullptr;
if (curr2.diffuseTextureName.size())
diff = model->neededTextures[curr2.diffuseTextureName];
ATexture* spec = nullptr;
if (curr2.specularTextureName.size())
spec = model->neededTextures[curr2.specularTextureName];
ATexture* norm = nullptr;
if (curr2.normalTextureName.size())
norm = model->neededTextures[curr2.normalTextureName];
m_materials.push_back(new Material(&curr2.outVB[0], curr2.outVB.size() * sizeof(float), &curr2.outTC[0], curr2.outTC.size() * sizeof(float), &curr2.outVN[0], curr2.outVN.size() * sizeof(float), &curr2.outTan[0], curr2.outTan.size() * sizeof(float), &curr2.outIB[0], curr2.ibCount, diff, curr2.diffuseColor, spec, curr2.shininess, norm));
ATexture* diffA = nullptr;
Texture* diff = nullptr;
if (curr2.diffuseTextureName.size()) {
diffA = model->neededTextures[curr2.diffuseTextureName];
diff = new Texture(diffA);
}
ATexture* specA = nullptr;
Texture* spec = nullptr;
if (curr2.specularTextureName.size()) {
specA = model->neededTextures[curr2.specularTextureName];
spec = new Texture(specA, true);
}
ATexture* normA = nullptr;
Texture* norm = nullptr;
if (curr2.normalTextureName.size()) {
normA = model->neededTextures[curr2.normalTextureName];
norm = new Texture(normA, true);
}
m_materials.push_back(std::make_tuple(diff, spec, norm, (float)curr2.diffuseColor.x, (float)curr2.diffuseColor.y, (float)curr2.diffuseColor.z, curr2.shininess));
unsigned int offset = vboPositions.size() / 3;
vboPositions.insert(vboPositions.end(), curr2.outVB.begin(), curr2.outVB.end());
vboTexCoords.insert(vboTexCoords.end(), curr2.outTC.begin(), curr2.outTC.end());
vboNormals.insert(vboNormals.end(), curr2.outVN.begin(), curr2.outVN.end());
vboTangents.insert(vboTangents.end(), curr2.outTan.begin(), curr2.outTan.end());
vboMaterialIndices.insert(vboMaterialIndices.end(), curr2.outVB.size() / 3, matCount);
if (offset)
std::for_each(curr2.outIB.begin(), curr2.outIB.end(), [offset](unsigned int& out) { out += offset; });
vboIndices.insert(vboIndices.end(), curr2.outIB.begin(), curr2.outIB.end());
delete m.second;
matCount++;
}
if (m_materials.size() > 32)
Error("Model exceedes 32 material limit!");
m_vao = new VertexArray;
m_vao->addBuffer(&vboPositions[0], vboPositions.size() * sizeof(float));
m_vao->pushFloat(3);
m_vao->finishBufferLayout();
m_vao->addBuffer(&vboTexCoords[0], vboTexCoords.size() * sizeof(float));
m_vao->pushFloat(2);
m_vao->finishBufferLayout();
m_vao->addBuffer(&vboNormals[0], vboNormals.size() * sizeof(float));
m_vao->pushFloat(3);
m_vao->finishBufferLayout();
m_vao->addBuffer(&vboTangents[0], vboTangents.size() * sizeof(float));
m_vao->pushFloat(3);
m_vao->finishBufferLayout();
m_vao->addBuffer(&vboMaterialIndices[0], vboMaterialIndices.size() * sizeof(int));
m_vao->pushInt(1);
m_vao->finishBufferLayout();
m_ib = new IndexBuffer(&vboIndices[0], vboIndices.size());
}
void Model::render(Shader* shader, bool onlyDepth) {
for (Material* curr : m_materials) {
curr->render(shader, onlyDepth);
m_vao->bind();
m_ib->bind();
if (!onlyDepth)
bindMaterials(shader);
glDrawElements(GL_TRIANGLES, m_ib->getCount(), GL_UNSIGNED_INT, nullptr);
}
void Model::bindMaterials(Shader* shader) {
int texSlot = 0;
for (unsigned int i = 0; i < m_materials.size(); i++) {
std::string currMatSuffix = std::to_string(i) + (std::string)"]";
Texture* diff;
if ((diff = std::get<0>(m_materials[i])) != nullptr) {
shader->setUniform(m_hasDiffString + currMatSuffix, true);
diff->bind(texSlot);
shader->setUniform(m_diffString + currMatSuffix, texSlot);
texSlot++;
}
else {
shader->setUniform(m_hasDiffString + currMatSuffix, false);
glm::vec3 color(std::get<3>(m_materials[i]), std::get<4>(m_materials[i]), std::get<5>(m_materials[i]));
shader->setUniform(m_diffColorString + currMatSuffix, color);
}
Texture* spec;
if ((spec = std::get<1>(m_materials[i])) != nullptr) {
shader->setUniform(m_hasSpecString + currMatSuffix, true);
spec->bind(texSlot);
shader->setUniform(m_specString + currMatSuffix, texSlot);
texSlot++;
}
else
shader->setUniform(m_hasSpecString + currMatSuffix, false);
Texture* norm;
if ((norm = std::get<2>(m_materials[i])) != nullptr) {
shader->setUniform(m_hasNormString + currMatSuffix, true);
norm->bind(texSlot);
shader->setUniform(m_normString + currMatSuffix, texSlot);
texSlot++;
}
else
shader->setUniform(m_hasNormString + currMatSuffix, false);
shader->setUniform(m_specPowerString + currMatSuffix, std::get<6>(m_materials[i]));
}
}
@ -350,8 +361,14 @@ namespace nf {
}
Model::~Model() {
for (Material* curr : m_materials) {
delete curr;
for (unsigned int i = 0; i < m_materials.size(); i++) {
Texture* curr;
if ((curr = std::get<0>(m_materials[i])) != nullptr)
Application::getApp()->getCurrentState()->m_texturesToDelete.insert(std::get<0>(m_materials[i]));
if ((curr = std::get<1>(m_materials[i])) != nullptr)
Application::getApp()->getCurrentState()->m_texturesToDelete.insert(std::get<1>(m_materials[i]));
if ((curr = std::get<2>(m_materials[i])) != nullptr)
Application::getApp()->getCurrentState()->m_texturesToDelete.insert(std::get<2>(m_materials[i]));
}
}
}

View File

@ -111,8 +111,8 @@ namespace nf {
};
m_quadVAO = new VertexArray;
m_quadVAO->addBuffer(quadVB, sizeof(quadVB));
m_quadVAO->push<float>(2);
m_quadVAO->push<float>(2);
m_quadVAO->pushFloat(2);
m_quadVAO->pushFloat(2);
m_quadVAO->finishBufferLayout();
m_quadIB = new IndexBuffer(quadIB, 6);
m_loadingText.create("NFLoadingText", Vec2(0.025, 0.044), Vec3(0.7, 0.7, 0.7));

View File

@ -44,8 +44,16 @@ namespace nf {
glAttachShader(m_id, fs);
if (gs) glAttachShader(m_id, gs);
glLinkProgram(m_id);
glValidateProgram(m_id);
int result;
glGetProgramiv(m_id, GL_LINK_STATUS, &result);
if (result != GL_TRUE) {
int length;
glGetProgramiv(m_id, GL_INFO_LOG_LENGTH, &length);
char* message = new char[length];
glGetProgramInfoLog(m_id, length, &length, message);
Error("OpenGL Error: " + (std::string)message);
}
glValidateProgram(m_id);
glGetProgramiv(m_id, GL_VALIDATE_STATUS, &result);
if (result != GL_TRUE) {
int length;

View File

@ -22,20 +22,29 @@ namespace nf {
m_lastStride = 0;
}
template<>
void VertexArray::push<float>(unsigned int count) {
void VertexArray::pushFloat(unsigned int count) {
if (m_lastBufferHasLayout)
Error("Tried to modify a vertex array's buffer after the layout was final!");
m_lastBufferLayout.push_back({ GL_FLOAT, count, GL_FALSE });
m_lastStride += count * sizeof(GL_FLOAT);
}
void VertexArray::pushInt(unsigned int count) {
if (m_lastBufferHasLayout)
Error("Tried to modify a vertex array's buffer after the layout was final!");
m_lastBufferLayout.push_back({ GL_INT, count, GL_FALSE });
m_lastStride += count * sizeof(GL_INT);
}
void VertexArray::finishBufferLayout() {
unsigned int offset = 0;
for (; m_attribute < m_lastBufferLayout.size(); m_attribute++) {
const VertexBufferElement& curr = m_lastBufferLayout[m_attribute];
glEnableVertexAttribArray(m_attribute);
glVertexAttribPointer(m_attribute, curr.count, curr.type, curr.normalized, m_lastStride, (const void*)offset);
if (curr.type != GL_INT)
glVertexAttribPointer(m_attribute, curr.count, curr.type, curr.normalized, m_lastStride, (const void*)offset);
else
glVertexAttribIPointer(m_attribute, curr.count, curr.type, m_lastStride, (const void*)offset);
offset += sizeof(curr.type) * curr.count;
}
m_lastBufferHasLayout = true;

View File

@ -17,7 +17,7 @@ namespace nf {
private:
void resize();
unsigned int m_FBO;
std::array<unsigned int, 4> m_textures; //TODO: Check this number
std::array<unsigned int, 4> m_textures;
unsigned int m_depth;
unsigned int m_width, m_height;

View File

@ -10,6 +10,7 @@ namespace nf {
class Renderer;
class Camera;
class Model;
class Texture;
class Gamestate {
public:
@ -32,6 +33,7 @@ namespace nf {
std::vector<NFObject*> m_nfObjects;
std::unordered_set<Model*> m_modelsToDelete;
std::unordered_set<Texture*> m_texturesToDelete;
protected:
Application* app;
Camera* camera;

View File

@ -4,39 +4,29 @@
#include "Utility.h"
namespace nf {
class Drawable;
class Texture;
class Shader;
class Material : public Drawable {
public:
Material(const void* vb, const size_t vbSize, const void* tc, const size_t tcSize, const void* vn, const size_t vnSize, const void* tan, const size_t tanSize, const void* ib, const unsigned int ibCount, ATexture* diffTex, Vec3& diffColor, ATexture* specTex, float shininess, ATexture* normalTex);
void render(Shader* shader, bool onlyDepth);
~Material();
private:
bool m_hasDiffuse = false;
Texture* m_diffuseTexture = nullptr;
Vec3 m_diffColor;
bool m_hasSpecular = false;
Texture* m_specularTexture = nullptr;
float m_shininess;
bool m_hasNormal = false;
Texture* m_normalTexture = nullptr;
};
class Model {
class Model : public Drawable {
public:
Model(AModel* model);
void render(Shader* shader, bool onlyDepth);
void bindMaterials(Shader* shader);
bool isBaseAsset();
~Model();
private:
bool m_base;
std::vector<Material*> m_materials;
std::vector<std::tuple<Texture*, Texture*, Texture*, float, float, float, float>> m_materials;
const std::string m_hasDiffString = "hasDiffuseTex[";
const std::string m_diffString = "diffuseTexture[";
const std::string m_diffColorString = "diffuseColor[";
const std::string m_hasSpecString = "hasSpecTex[";
const std::string m_specString = "specularTexture[";
const std::string m_hasNormString = "hasNormTex[";
const std::string m_normString = "normalTexture[";
const std::string m_specPowerString = "specPower[";
};
}

View File

@ -15,8 +15,8 @@ namespace nf {
VertexArray();
void addBuffer(const void* data, const size_t size);
template<typename T>
void push(unsigned int count);
void pushFloat(unsigned int count);
void pushInt(unsigned int count);
void finishBufferLayout();
void bind();
void setBufferData(unsigned int buffer, const void* data, const size_t dataSize);