質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
87.20%
GLFW

GLFWは、OpenGLを使用してアプリ開発を行うためのフレームワークです。Macにも対応しているマルチプラットフォームであることが特徴。ウィンドウ管理、解像度切り替え、入力管理などの機能を持ちます。

OpenGL

OpenGLは、プラットフォームから独立した、デスクトップやワークステーション、モバイルサービスで使用可能な映像処理用のAPIです。

MacOS(OSX)

MacOSとは、Appleの開発していたGUI(グラフィカルユーザーインターフェース)を採用したオペレーションシステム(OS)です。Macintoshと共に、市場に出てGUIの普及に大きく貢献しました。

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

GLSL

GLSL (OpenGL Shading Language) はC言語をベースとしたシェーディング言語です。

解決済

GLFWで画面のサイズに関わらず図形を固定の大きさに設定したいです。

code413
code413

総合スコア0

GLFW

GLFWは、OpenGLを使用してアプリ開発を行うためのフレームワークです。Macにも対応しているマルチプラットフォームであることが特徴。ウィンドウ管理、解像度切り替え、入力管理などの機能を持ちます。

OpenGL

OpenGLは、プラットフォームから独立した、デスクトップやワークステーション、モバイルサービスで使用可能な映像処理用のAPIです。

MacOS(OSX)

MacOSとは、Appleの開発していたGUI(グラフィカルユーザーインターフェース)を採用したオペレーションシステム(OS)です。Macintoshと共に、市場に出てGUIの普及に大きく貢献しました。

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

GLSL

GLSL (OpenGL Shading Language) はC言語をベースとしたシェーディング言語です。

1回答

0評価

1クリップ

1604閲覧

投稿2019/07/26 11:28

編集2022/01/12 10:58

環境:
MacOS 10.14.5
Xcode 10.3

床井研究室様の『GLFWによるOpenGL入門』(http://marina.sys.wakayama-u.ac.jp/~tokoi/GLFWdraft.pdf)を見て勉強しています。

第6章100Pまで行い、下記のソース(字数の都合上コメントを一部省略)ができたのですが、起動後は真ん中に(図1)、ウィンドウのサイズを変えると図形の位置が変わり、そこからウィンドウを移動すると再び図形の位置が戻ります。(図2,図3)
イメージ説明
---図1 起動直後---
イメージ説明
---図2 サイズ変更後---
イメージ説明
---図3 サイズ変更後、移動---

main

#include<cstdlib> #include<iostream> #include<fstream> #include<vector> #include<memory> #include<GL/glew.h> #include<GLFW/glfw3.h> #include "Window.h" #include "Shape.h" // シェーダオブジェクトのコンパイル結果 GLboolean printShaderInfoLog(GLuint shader,const char *str){ GLint status; glGetShaderiv(shader, GL_COMPILE_STATUS, &status); if(status == GL_FALSE) std :: cerr << "Compile Error in " << str << std::endl; GLsizei bufSize; glGetShaderiv(shader,GL_INFO_LOG_LENGTH,&bufSize); if(bufSize > 1){ std::vector<GLchar> infoLog(bufSize); GLsizei length; glGetShaderInfoLog(shader,bufSize,&length,&infoLog[0]); std::cerr << &infoLog[0] << std::endl; } return static_cast<GLboolean>(status); } //プログラムオブジェクトのリンク結果 GLboolean printProgramInfoLog(GLuint program){ GLint status; glGetProgramiv(program,GL_LINK_STATUS,&status); if(status == GL_FALSE) std::cerr << "Link Error" << std::endl; GLsizei bufsize; glGetProgramiv(program,GL_INFO_LOG_LENGTH,&bufsize); if(bufsize > 1){ std::vector<GLchar> infoLog(bufsize); GLsizei length; glGetProgramInfoLog(program,bufsize,&length,&infoLog[0]); std::cerr << &infoLog[0] << std::endl; } return static_cast<GLboolean>(status); } //プログラムオブジェクト作成 GLuint createProgram(const char *vsrc, const char *fsrc){ const GLuint program(glCreateProgram()); if(vsrc != NULL){ //バーテックスシェーダのシェーダオブジェクトを作成、組込 const GLuint vobj(glCreateShader(GL_VERTEX_SHADER)); glShaderSource(vobj,1,&vsrc,NULL); glCompileShader(vobj); if(printShaderInfoLog(vobj,"vertex shader")) glAttachShader(program,vobj); glDeleteShader(vobj); } if(fsrc != NULL){ //フラグメントシェーダのシェーダオブジェクトを作成、組込 const GLuint fobj(glCreateShader(GL_FRAGMENT_SHADER)); glShaderSource(fobj,1,&fsrc,NULL); glCompileShader(fobj); if(printShaderInfoLog(fobj,"fragment shader")) glAttachShader(program,fobj); glDeleteShader(fobj); } glBindAttribLocation(program,0,"position"); glBindFragDataLocation(program,0,"fragment"); glLinkProgram(program); if(printProgramInfoLog(program)) return program; glDeleteProgram(program); return 0; } //シェーダのソースを読み込んだメモリを返す bool readShaderSource(const char *name,std::vector<GLchar> &buffer){ if(name == NULL) return false; std::ifstream file(name,std::ios::binary); if(file.fail()){ std::cerr << "Error: Can't open source: " << name << std::endl; return false; } file.seekg(0L,std::ios::end); GLsizei length = static_cast<GLsizei>(file.tellg()); //ファイルサイズのメモリ確保(+1では動かなかったので4に) buffer.resize(length + 4); file.seekg(0L,std::ios::beg); file.read(buffer.data(),length); buffer[length] = '\n'; if(file.fail()){ std::cerr << "Error: Couldn't read source:" << name << std::endl; file.close(); return false; } file.close(); return true; } //シェーダのソースを読み込んでプログラムオブジェクトを作成 GLuint loadProgram(const char *vert,const char *frag){ std::vector<GLchar> vsrc; const bool vstat(readShaderSource(vert, vsrc)); std::vector<GLchar> fsrc; const bool fstat(readShaderSource(frag, fsrc)); return vstat && fstat ? createProgram(vsrc.data(), fsrc.data()) : 0; } constexpr Object::Vertex rectangleVertex[] = { {-0.5f ,-0.5f }, { 0.5f ,-0.5f }, { 0.5f , 0.5f }, {-0.5f , 0.5f } }; int main() { if(glfwInit() == GL_FALSE){ std::cerr << "Can't initialize GLFW" << std::endl; return 1; } atexit(glfwTerminate); // Version 3.2 Core Profile を選択 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2); glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); Window window; glClearColor(1.0f, 1.0f, 1.0f, 0.0f); //プログラムオブジェクト作成 const GLuint program(loadProgram("point.vert","point.frag")); // uniform変数の場所を取得 const GLint sizeLoc(glGetUniformLocation(program, "size")); const GLint scaleLoc(glGetUniformLocation(program,"scale")); // 図形データ作成 std::unique_ptr<const Shape> shape(new Shape(2, 4, rectangleVertex)); while(window.shouldClose() == GL_FALSE) { glClear(GL_COLOR_BUFFER_BIT); //シェーダプログラムの使用開始 glUseProgram(program); // uniform変数に値を設定 glUniform2fv(sizeLoc, 1, window.getSize()); glUniform1f(scaleLoc, window.getScale()); //図形を描画 shape -> draw(); window.swapBuffers(); } }

Window

#pragma once #include <iostream> #include <GL/glew.h> #include <GLFW/glfw3.h> // ウィンドウ関連の処理 class Window{ GLFWwindow *const window; //ウィンドウのサイズ GLfloat size[2]; //ワールド座標系に対するデバイス座標系の拡大率 GLfloat scale; public: //コンストラクタ Window(int width = 640, int height = 480, const char *title = "Hello!") : window(glfwCreateWindow(width, height, title, NULL, NULL)) , scale(100.0f) { if(window == NULL) { //ウィンドウが作成できなかった std::cerr << "Can't create GLFW window." << std::endl; exit(1); } //現在のウィンドウを処理対象にする glfwMakeContextCurrent(window); //GLEWを初期化する glewExperimental = GL_TRUE; if(glewInit() != GLEW_OK) { //GLEWの初期化に失敗した std::cerr << "Can't initialize GLEW" << std::endl; exit(1); } //垂直同期のタイミングを待つ glfwSwapInterval(1); //このインスタンスの this ポインタを記録しておく glfwSetWindowUserPointer(window, this); //ウィンドウのサイズ変更時に呼び出す処理の登録 glfwSetWindowSizeCallback(window,resize); //開いたウィンドウの初期設定 resize(window,width,height); } virtual ~Window(){ glfwDestroyWindow(window); } //ウィンドウを閉じるべきかを判定する int shouldClose() const{ return glfwWindowShouldClose(window); } //カラーバッファを入れ替えてイベントを取り出す void swapBuffers(){ glfwSwapBuffers(window); glfwWaitEvents(); } //ウィンドウのサイズを取り出す const GLfloat *getSize() const { return size; } //ワールド座標系に対するデバイス座標系の拡大率を取り出す GLfloat getScale() const{ return scale; } // ウィンドウのサイズ変更時の処理 static void resize(GLFWwindow *const window,int width,int height) { //ウィンドウ全体をビューポートに設定する glViewport(0, 0, width, height); //このインスタンスのthisポインタを得る Window *const instance(static_cast<Window *>(glfwGetWindowUserPointer(window))); if(instance != NULL){ //開いたウィンドウのサイズを保存する instance->size[0] = static_cast<GLfloat>(width); instance->size[1] = static_cast<GLfloat>(height); } } };

Object

#pragma once #include<GL/glew.h> //図形データ class Object{ //頂点配列、バッファ GLuint vao; GLuint vbo; public: struct Vertex{ GLfloat position[2]; }; //コンストラクタ Object(GLint size,GLsizei vertexcount,const Vertex *vertex){ //頂点配列,バッファオブジェクト glGenVertexArrays(1,&vao); glBindVertexArray(vao); glGenBuffers(1,&vbo); glBindBuffer(GL_ARRAY_BUFFER,vbo); glBufferData(GL_ARRAY_BUFFER,vertexcount * sizeof(Vertex),vertex,GL_STATIC_DRAW); //結合されている頂点バッファオブジェクトをin変数から参照できる様にする glVertexAttribPointer(0,size,GL_FLOAT,GL_FALSE,0,0); glEnableVertexAttribArray(0); } virtual ~Object(){ glDeleteBuffers(1,&vao); glDeleteBuffers(1,&vbo); } private: Object(const Object &o); Object &operator = (const Object &o); public: //頂点オブジェクトの統合 void bind() const{ //描画する頂点配列オブジェクトを指定 glBindVertexArray(vao); } };

Shape

#pragma once #include<memory> //図形データ #include "Object.h" //図形の描画 class Shape{ std::shared_ptr<const Object> object; protected: const GLsizei vertexcount; public: Shape(GLint size,GLsizei vertexcount,const Object::Vertex *vertex) :object(new Object(size,vertexcount,vertex)) ,vertexcount(vertexcount) { } //描画 void draw() const{ object -> bind(); execute(); } virtual void execute() const{ glDrawArrays(GL_LINE_LOOP,0,vertexcount); } };

VertexShader

#version 150 core uniform vec2 size; uniform float scale; in vec4 position; void main(){ gl_Position = vec4(2.0 * scale/size, 1.0 , 1.0) * position; //二つ目の1.0のの前に空白を入れると動いた

FragmentShader

#version 150 core out vec4 fragment; void main(){ fragment = vec4(1.0, 0.0, 0.0, 1.0); }

ウィンドウのサイズが切り替わっても真ん中に表示したいのですが、移動するまでは左下の位置のままです、どうかよろしくお願いします。

追伸
バーテックスシェーダに1つスペースを加えたら、図形が横長になる問題とサイズがウィンドウに比例する問題は自己解決したので質問の画像、文章などを差し替えさせていただきました。
現在は画面サイズ変更に伴う図形の移動について悩んでいます。

良い質問の評価を上げる

以下のような質問は評価を上げましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

気になる質問をクリップする

クリップした質問は、後からいつでもマイページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

  • プログラミングに関係のない質問
  • やってほしいことだけを記載した丸投げの質問
  • 問題・課題が含まれていない質問
  • 意図的に内容が抹消された質問
  • 過去に投稿した質問と同じ内容の質問
  • 広告と受け取られるような投稿

評価を下げると、トップページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

まだ回答がついていません

会員登録して回答してみよう

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
87.20%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問

同じタグがついた質問を見る

GLFW

GLFWは、OpenGLを使用してアプリ開発を行うためのフレームワークです。Macにも対応しているマルチプラットフォームであることが特徴。ウィンドウ管理、解像度切り替え、入力管理などの機能を持ちます。

OpenGL

OpenGLは、プラットフォームから独立した、デスクトップやワークステーション、モバイルサービスで使用可能な映像処理用のAPIです。

MacOS(OSX)

MacOSとは、Appleの開発していたGUI(グラフィカルユーザーインターフェース)を採用したオペレーションシステム(OS)です。Macintoshと共に、市場に出てGUIの普及に大きく貢献しました。

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

GLSL

GLSL (OpenGL Shading Language) はC言語をベースとしたシェーディング言語です。